天天看點

zeromq源碼分析筆記之架構

1、zmq概述

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 端單向的推送資料流。

2、zmq架構

2.1、zmq整體架構

zeromq幾乎所有I/O操作都是異步的,每個zmq i/o 線程(與實際線程不同)都有與之綁定的Poller,Poller采用經典的Reactor模式實作,Poller根據不同作業系統平台使用不同的網絡I/O模型(select、poll、epoll、devpoll、kequeue等)。在zeromq中,zmq_socket也被看成是一個zmq io線程。每個線程内含一個信箱,用于線程與線程間傳遞指令(後面會詳細講),在建立zmq io線程時,會把信箱句柄加到Poller中,用于監聽是否有指令到達。當client端開始發起連接配接或者server端開始監聽時,會在主線程建立zmq_connector或者zmq_listener,主線程使用zmq_socket的mailbox發送指令給io線程,将其綁定到io線程中,io線程會把zmq_connector或者zmq_listener含有的句柄加入Poller中,以偵聽讀寫事件。Client端與Server端都是通過Session來管理連接配接和通信,一個session代表一次會話,每個Session都會關聯到相應的讀/寫管道, 主線程收發消息隻是分别從管道中讀/寫資料。Session并不實際跟kernel交換I/O資料,而是通過plugin到Session中的Engine來與kernel交換I/O資料。

zeromq源碼分析筆記之架構

2.2zmq内部架構

zmq的内部架構涉及到zmq全局變量的管理,并發模型,線程模型(主線程,i/o線程,回收線程,zmq_socket線程,存活于線程中的對象),對象回收模型(對象樹),消息的組織等,要想比較順手的讀懂源碼,還是需要先了解一下這些結構,在zmq的官方站點已經給出來了詳細的講解,也有前輩進行了翻譯:

Internal Architecture of libzmq,ZeroMQ的内部架構

http://www.aosabook.org/en/zeromq.html,<摘錄>開源軟體架構-ZeroMQ

3、zmq基本流程

下面這幅zmq的基本流程圖有助于整體把握zmq的流程,這幅圖是由前輩總結的,來源于ZeroMQ研究與應用分析,(不知道是否是原創,有很多一樣的博文,分不清原創是誰),不過新版的zmq已經不建議使用zmq_init初始化上下文語境了,新版建議使用zmq_new來建立上下文,關于新版zmq的一個詳細流程在第4節會給出。

zeromq源碼分析筆記之架構

4、zmq對象互動

序列圖有助于了解對象狀态變遷,下圖描述的是用戶端的對象狀态變遷。zmq_socket以ZMQ_REQ模式執行個體化,用以進行tcp通信:

void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");
           
zeromq源碼分析筆記之架構

4、zmq類層次

zeromq源碼分析筆記之架構

①、object_t,主要用于發送指令和處理指令,所有繼承object_t的子類都具備該類的功能

②、io_thread_t,内含一個poller,可監聽句柄的讀、寫、異常狀态,繼承自object_t,具有接收指令、處理指令、發送指令的功能

③、io_object_t,可以擷取一個io_thread_t的poller,進而具備poller功能,所有繼承自該類的子類都具有pollere功能,可監聽句柄的讀、寫、異常狀态

④、reaper_t,zmq的回收線程

⑤、own_t,zmq的對象樹結點,或者說多叉樹的結點,其主要用于對象的銷毀,可以想到,對象的銷毀就是這棵樹的銷毀過程,必須要使用深度優先的算法來銷毀。關于zmq對象樹在Internal Architecture of libzmq有詳細講解

⑥、tcp_connector_t,zmq_socket的連接配接器,使用她來建立tcp連接配接

⑦、tcp_listener_t,zmq_socket的監聽器

⑧、stream_engine,負責處理io事件中的一種----網絡事件,把網絡位元組流轉換成zeromq的msg_t消息傳遞給session_base_t。另外一些和版本相容相關的雜務也stream_engine處理的。stream_engine_t處理完雜務,到session_base_t就隻看見msg_t了。

⑨、session_base_t,管理zmq_socket的連接配接和通信,主要與engine進行交換

⑩、socket_base_t,zeromq的socket,在zmq中,被當成一種特殊的”線程“,具有收發指令的功能

繼續閱讀