ZeroMQ 的模式

在需要並行化處理數據的時候,採用消息隊列通訊的方式來協作,比採用共享狀態的方式要好的多。Erlang ,Go 都使用這一手段來讓並行任務之間協同工作。

最近讀完了 ZeroMQGuide。寫的很不錯。前幾年一直有做類似的工作,但是自己總結的不好。而 ZeroMQ 把消息通訊方面的模式總結的很不錯。

ZeroMQ 並不是一個對 socket 的封裝,不能用它去實現已有的網絡協議。它有自己的模式,不同於更底層的點對點通訊模式。它有比 tcp 協議更高一級的協議。(當然 ZeroMQ 不一定基於 TCP 協議,它也可以用於進程間和進程內通訊。)它改變了通訊都基於一對一的連接這個假設。

ZeroMQ 把通訊的需求看成四類。其中一類是一對一結對通訊,用來支持傳統的 TCP socket 模型,但並不推薦使用。常用的通訊模式只有三類。

  1. 請求迴應模型。由請求端發起請求,並等待迴應端迴應請求。從請求端來看,一定是一對對收發配對的;反之,在迴應端一定是發收對。請求端和迴應端都可以是 1:N 的模型。通常把 1 認爲是 server ,N 認爲是 Client 。ZeroMQ 可以很好的支持路由功能(實現路由功能的組件叫作 Device),把 1:N 擴展爲 N:M (只需要加入若干路由節點)。從這個模型看,更底層的端點地址是對上層隱藏的。每個請求都隱含有迴應地址,而應用則不關心它。

  2. 發佈訂閱模型。這個模型裏,發佈端是單向只發送數據的,且不關心是否把全部的信息都發送給訂閱端。如果發佈端開始發佈信息的時候,訂閱端尚未連接上來,這些信息直接丟棄。不過一旦訂閱端連接上來,中間會保證沒有信息丟失。同樣,訂閱端則只負責接收,而不能反饋。如果發佈端和訂閱端需要交互(比如要確認訂閱者是否已經連接上),則使用額外的 socket 採用請求迴應模型滿足這個需求。

  3. 管道模型。這個模型裏,管道是單向的,從 PUSH 端單向的向 PULL 端單向的推送數據流。

任何分佈式,並行的需求,都可以用這三種模型組合起來解決問題。ZeroMQ 只專注和解決了消息通訊這一基本問題,乾的非常漂亮。

基於定義好的模型,我們可以看到,api 可以實現的非常簡單易用。我們不再需要 bind/listen/accept 來架設服務器,因爲這個模型天然是 1:N 而不是 1:1 的,不需要爲每個通道保留一個句柄。我們也不必在意 server 是否先啓動(bind),而後才能讓 client 工作起來(connect)。

這以上模型中,關注的是通訊雙方的職責,而不是實現的方式:監聽端口還是連接對方端口。對於複雜的多進程協同工作的系統, 不必糾結於進程啓動的次序(在我前幾年設計的系統中,啓動腳本寫起來就非常麻煩)。

使用 ZeroMQ 不必在意底層實現是使用短連接還是長連接方式。ZeroMQ 中的 Transient (短暫) 和 Durable (持久) socket 也並非區別於實現層是否保持了 tcp 連接。而是概念上的不同。對於 Durable socket ,其生命期可以長於一個進程的生命期,即使進程退出,再次啓動後依舊可以維持繼續之前的 socket 。當然,這並不是幫助你挽救你的程序因出錯而崩潰的。它只是提出這個模式,讓你根據設計需要可以實現。對於 ZeroMQ ,如有需求(若內存有限),甚至把數據傳輸的 buffer 放到磁盤上。


對於網絡遊戲,我覺得基於 ZeroMQ 來架構服務器非常合適。對於玩家 Client - Server 部分倒不必使用 ZeroMQ ,而可以寫一個前端程序,比如前些年寫過的一篇 blog 中提到的連接服務器依然適用。這個連接服務器對內的服務集羣則可以用 ZeroMQ 的協議通訊。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章