蔡建坤
本文針對空管系統間信息交互的困難,研究分析ZeroMQ 的運作原理、支持的工作模式,并描述了使用ZeroMQ 作為空管系統信息交換的通信模型,為空管應用系統間信息交互提供基礎研究。
ZeroMQ 專為可擴展的分布式或并發應用程序而設計,是一個高性能的異步消息庫[1]。按TCP/IP 協議,ZeroMQ 可作為新的網絡通信層,位于應用層和傳輸層之間,是一個可以并行工作并在分布式系統之間傳播的可擴展層。與消息中間件不同的地方,ZeroMQ 不需要啟動任何專用的消息代理。ZeroMQ 可視為是一個套接字Socket 庫,看起來像一個框架,使套接字編程更高效,更簡單,更清晰。
當使用ZeroMQ,數據流的操作如圖1 所示,通信中幾乎一切IO 操作都為異步的,主線程不會被阻塞。ZeroMQ 根據調用zmk_init 函數時傳輸的形參創建相同數量的IO 線程。每個IO Thread 都有與之綁定的“ Poller”,依據操作系統的不同的平臺,“Poller”應用不同的網絡IO 模型(Kequeue、Select、Epoll 、Poll、Devpoll 等)。主 線 程和IO 線程通過郵箱(Mail Box)進行通信。當服務器開始聽或客戶端發起連接時它會創建zmk_connecter 或zmk_listener 在主要線程,通過郵箱(Mail Box)與IO 線程連接,以及IO 線程增加zmk_connecter 或zmk_listener 用于聽讀/寫事件。當服務器首次與客戶端通信時,它會創建zmk_init 以發送身份驗證。檢查完成后,雙方將為此連接創建會話,然后雙方將通過會話進行通信。每個會話都連接到管道,主線程僅通過從管道讀取/寫入數據來發送和接收消息。會話實際上并不與內核共享IO 數據,相反,IO 數據在會話中通過“plugin”到“Session”中的“Engine”與內核交換。
圖1 ZeroMQ內部數據架構圖
ZeroMQ 提供四種通信協議,格式為ipc://,inproc://,tcp://,pgm://,分別對應進程間,進程內,機器間和廣播。通信協議非常易于配置,通過類似于URL 的字符串指定,ZeroMQ 自動解釋協議,地址,端口號和其他信息[1]。
ZeroMQ 將消息通信分成推拉模型、一對一結對模型、發布訂閱模型、請求回應模型4 種模型。這四個模型基本滿足了空管系統的網絡通信模型,在實踐中,您可以組合兩個或更多模型進行使用。
1)一對一結對模型。消息一對一通信模型的最簡單通信模型,可以被視為TCP 連接,但TCP 服務器只能接受一個連接。與請求回應模型不同,數據可以在兩個方向上運行。
2)請求回應模型。請求端提出請求,等待回應端答復,請求與回應對應。對應請求端來說,它是一個發—收配對,對于回應端來說,它是一個收—發配對。相對于與一對一結對模型,其區別在于可以是N 個(N 大于等于1)的請求。這個模型主要用于任務分配和遠程調用[2]。
3)發布訂閱模式。發布者單向傳播數據,不管數據是否被客戶訂閱到。如果發布者在開始輸出時沒有連接,發布者將立即丟棄信息。沒有連接和信息的丟失問題可以通過在組合請求響應模型來解決。訂閱者只負責接收,但不負責提供反饋。如果訂閱速度快或與發布者相同,數據可以及時使用,如果處理速度慢,數據會堆積到訂閱者身上。該模型主要用于數據分發[3]。
4)推拉模式。服務器用作推送端,客戶使用作為拉取端,如果多個客戶端同時連接到服務器,該服務將在內部執行負載平衡發布到客戶端上。與發布訂閱者模型相比,此模型不丟棄信息,如消費者能力不足,模型為消費者提供了并行處理選項[3]。該模型用于平行多任務處理場景。
ZeroMQ 具有以下特征:
1)異步,支持高并發,比TCP 更快,適用于大型集群和分布式計算;
2)提供異步I/O 模式,支持超過 30 種的編程語言,包括所有主流編程語言;
3)提供多種消息傳遞機制和內置豐富的組合模式可用于簡化大型分步式計算架構;
4)良好的跨平臺性,支持多種操作系統;
5)擁有iMatik 在商業層面的支持,它是完全免費的,且開發者社區活躍,發展迅速。
本文介紹的四種ZeroMQ 模型總結了空管系統網絡通信的通用模型,在實踐中,可根據空管系統應用需求組合兩種或更多模型來構建解決方案。如代理模式,此模式主要用于按需擴展請求響應模式。如果需要擴展多響應服務器,可以使用代理模式。ROUTER 對應于一個請求,它等同于響應服務器,它執行先收后發,接收和發送循環。當它在內部從前端接收請求,然后發送DEALER 請求,該請求接收ROUTER 消息并將消息發送給響應者,但DEALER 面臨N 個響應者。通過代理模式的轉變,請求響應模式將自動擴展容量。如果將此機制集成到操作中,則代理模式是異步的。與異步的接線員類似,將N個請求與M 個響應連接起來。并確保它們是平衡的。
因此,可以說ZeroMQ 幾乎可以滿足現有的通信要求,無論是單機還是分布式。
以下通過模擬客戶端和服務端的通信,說明采用ZeroMQ 進行系統間信息交換時的通信模型。
采用ZeroMQ 進行空管系統通信時,客戶端或服務端的程序都設計為由主線程和IO 線程組成。主線程主要負責創建或銷毀IO 線程通信的上下文和作為消息的生產者或消費者;IO 線程則負責利用ZeroMQ 進行通信。下面各自對客戶端和服務端的主線程和IO 線程的工作流程進行說明。
采用ZeroMQ 通信時,客戶端或服務器程序設計為由主線程和IO 線程組成。主線程主要負責創建或銷毀IO 通信的上下文,既不是制造消息也不是消息的消費者,IO 線程負責與ZeroMQ 通信。下面是主線程和和IO 線程的工作流程。
2.5.1 客戶端的主線程的工作流程
1)調用zmq_init 創建context 指針;
2)創建IO 線程對象;
3)創建mail box;
4)啟動IO 線程;
5)調用zmq_socket 根據指定模式創建socket指針;
6)調用zmq_connect 根據指定通信方式連接服務端;
7)創建session_t 指針;
8)添加會話指針到IO 線程;
9)創建zmq_connector_t 指針;
10)連接到connector,由IO 現場與服務端建立連接;
11)調用zmq_send 將消息寫入與會話相關聯的通道;
12)調用zmq_close 關閉套接字;
13)調用zmq_term 銷毀上下文。
2.5.2 客戶端的IO 線程的工作流程
1)IO 線程調用start_connting 函數連接服務端;
2)在連接成功后,發送peer_identity;
3)通過會話讀取管道中的消息;
4)通過engine 向服務器發送消息。
2.5.3 服務端主線程的工作流程
1)調用zmq_init 創建context 指針;
2)創建IO 線程對象;
3)創建mail box;
4)啟動IO 線程;
5)調用zmq_socket 根據指定的模式創建socket 指針;
6)調用zmq_bind 根據指定的通信方式監聽客戶端的連接請求;
7)創建監聽者指針;
8)Attach 到監聽者;
9)調用zmq_recv 從session 關聯管道讀取消息;
10)通信結束時,調用zmq_close 關閉socket;
11)調用zmq_term 銷毀context。
2.5.4 服務端IO 線程的工作流程
1)接受客戶端連接請求,創建zmq_init_t 指針;
2)創建sesstion_t 指針;
3)通過engine 從客戶端接收消息;
4)通過sesstion 將消息寫入管道。
ZeroMQ 使用組合多模式在空管系統網絡中完成通信任務和擴展任務,同時,它隱藏了復雜的網絡編程細節,如協議橋接、重連、補發等等。除了為不同的操作系統提供完整的編程接口外,還可以減少移植問題。本文通過研究ZeroMQ 的運作原理、支持的工作模式,描述了使用ZeroMQ 作為空管系統信息交換的通信模型,為空管應用系統間信息交互提供基礎研究成果。