Java開發大型互聯網解決分散式系統管理性之分散式消息隊列應用

引言

什麼是分散式計算?所謂分散式計算是一門計算機科學,它研究如何把一個需要非常巨大的計算能力才能解決的問題分成許多小的部分,然後把這些部分分配給許多計算機進行處理,最後把這些計算結果綜合起來得到最終的結果。分散式網路存儲技術是將數據分散的存儲於多台獨立的機器設備上。分散式網路存儲系統採用 可擴展的系統結構,利用多台存儲伺服器分擔存儲負荷,利用位置伺服器定位存儲信息,不但解決了傳統集中式存儲系統中單存儲伺服器的瓶頸問題,還提高了系統的可靠性、可用性和擴展性。

解決分散式系統可管理性

目錄服務(ZooKeeper)

分散式系統是一個由很多進程組成的整體,這個整體中每個成員部分,都會具備一些狀態,比如自己的負責模塊,自己的負載情況,對某些數據的掌握等等。而這些和其他進程相關的數據,在故障恢復、擴容縮容的時候變得非常重要。

Advertisements

簡單的分散式系統,可以通過靜態的配置文件,來記錄這些數據:進程之間的連接對應關係,他們的IP地址和埠,等等。然而一個自動化程度高的分散式系統,必然要求這些狀態數據都是動態保存的。這樣才能讓程序自己去做容災和負載均衡的工作。

一些程序員會專門自己編寫一個DIR服務(目錄服務),來記錄集群中進程的運行狀態。集群中進程會和這個DIR服務產生自動關聯,這樣在容災、擴容、負載均衡的時候,就可以自動根據這些DIR服務里的數據,來調整請求的發送目地,從而達到繞開故障機器、或連接到新的伺服器的操作。

然而,如果我們只是用一個進程來充當這個工作。那麼這個進程就成為了這個集群的「單點」——意思就是,如果這個進程故障了,那麼整個集群可能都無法運行的。所以存放集群狀態的目錄服務,也需要是分散式的。幸好我們有ZooKeeper這個優秀的開源軟體,它正是一個分散式的目錄服務區。

Advertisements

ZooKeeper可以簡單啟動奇數個進程,來形成一個小的目錄服務集群。這個集群會提供給所有其他進程,進行讀寫其巨大的「配置樹」的能力。這些數據不僅僅會存放在一個ZooKeeper進程中,而是會根據一套非常安全的演算法,讓多個進程來承載。這讓ZooKeeper成為一個優秀的分散式數據保存系統。

由於ZooKeeper的數據存儲結構,是一個類似文件目錄的樹狀系統,所以我們常常會利用它的功能,把每個進程都綁定到其中一個「分枝」上,然後通過檢查這些「分支」,來進行伺服器請求的轉發,就能簡單的解決請求路由(由誰去做)的問題。另外還可以在這些「分支」上標記進程的負載的狀態,這樣負載均衡也很容易做了。

目錄服務是分散式系統中最關鍵的組件之一。而ZooKeeper是一個很好的開源軟體,正好是用來完成這個任務。

消息隊列服務(ActiveMQ、ZeroMQ、Jgroups)

兩個進程間如果要跨機器通訊,我們幾乎都會用TCP/UDP這些協議。但是直接使用網路API去編寫跨進程通訊,是一件非常麻煩的事情。除了要編寫大量的底層socket代碼外,我們還要處理諸如:如何找到要交互數據的進程,如何保障數據包的完整性不至於丟失,如果通訊的對方進程掛掉了,或者進程需要重啟應該怎樣等等這一系列問題。這些問題包含了容災擴容、負載均衡等一系列的需求。

為了解決分散式系統進程間通訊的問題,人們總結出了一個有效的模型,就是「消息隊列」模型。消息隊列模型,就是把進程間的交互,抽象成對一個個消息的處理,而對於這些消息,我們都有一些「隊列」,也就是管道,來對消息進行暫存。每個進程都可以訪問一個或者多個隊列,從裡面讀取消息(消費)或寫入消息(生產)。由於有一個緩存的管道,我們可以放心的對進程狀態進行變化。當進程起來的時候,它會自動去消費消息就可以了。而消息本身的路由,也是由存放的隊列決定的,這樣就把複雜的路由問題,變成了如何管理靜態的隊列的問題。

一般的消息隊列服務,都是提供簡單的「投遞」和「收取」兩個介面,但是消息隊列本身的管理方式卻比較複雜,一般來說有兩種。一部分的消息隊列服務,提倡點對點的隊列管理方式:每對通信節點之間,都有一個單獨的消息隊列。這種做法的好處是不同來源的消息,可以互不影響,不會因為某個隊列的消息過多,擠佔了其他隊列的消息緩存空間。而且處理消息的程序也可以自己來定義處理的優先順序——先收取、多處理某個隊列,而少處理另外一些隊列。

但是這種點對點的消息隊列,會隨著集群的增長而增加大量的隊列,這對於內存佔用和運維管理都是一個複雜的事情。因此更高級的消息隊列服務,開始可以讓不同的隊列共享內存空間,而消息隊列的地址信息、建立和刪除,都採用自動化的手段。——這些自動化往往需要依賴上文所述的「目錄服務」,來登記隊列的ID對應的物理IP和埠等信息。比如很多開發者使用ZooKeeper來充當消息隊列服務的中央節點;而類似Jgropus這類軟體,則自己維護一個集群狀態來存放各節點今昔。

另外一種消息隊列,則類似一個公共的郵箱。一個消息隊列服務就是一個進程,任何使用者都可以投遞或收取這個進程中的消息。這樣對於消息隊列的使用更簡便,運維管理也比較方便。不過這種用法下,任何一個消息從發出到處理,最少進過兩次進程間通信,其延遲是相對比較高的。並且由於沒有預定的投遞、收取約束,所以也比較容易出BUG。

不管使用那種消息隊列服務,在一個分散式伺服器端系統中,進程間通訊都是必須要解決的問題,所以作為伺服器端程序員,在編寫分散式系統代碼的時候,使用的最多的就是基於消息隊列驅動的代碼,這也直接導致了EJB3.0把「消息驅動的Bean」加入到規範之中。

總結

以上是對Java開發大型互聯網解決分散式系統管理性之分散式消息隊列應用,分享給大家,希望大家可以了解什麼是Java開發大型互聯網解決分散式系統管理性之分散式消息隊列應用。覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持。(吹一波,233~~)這個是我Java內部資料分享交流群:469717771 驗證碼:頭條(06 必過)歡迎大家的加入!!!

Advertisements

你可能會喜歡