python中zmq的基礎三種模式

ZMQ 的三個基本模型

ZMQ 提供了三個基本的通信模型,分別是“Request-Reply “,”Publisher-Subscriber“,”Parallel Pipeline”

  1. 請求應答模式(Request-Reply)(rep 和 req)
    消息雙向的,有來有往,req端請求的消息,rep端必須答覆給req端
  2. 訂閱發佈模式 (pub 和 sub)
    消息單向的,有去無回的。可按照發布端可發佈制定主題的消息,訂閱端可訂閱喜歡的主題,訂閱端只會收到自己已經訂閱的主題。發佈端發佈一條消息,可被多個訂閱端同事收到。
  3. push pull模式
    消息單向的,也是有去無回的。push的任何一個消息,始終只會有一個pull端收到消息.

1.ZMQ 的 Request-Reply
由 Client 發起請求,並等待 Server 迴應請求。請求端發送一個簡單的 hello,服務端則迴應一個 world。請求端和服務端都可以是 1:N 的模型。通常把 1 認爲是 Server ,N 認爲是 Client 。ZMQ 可以很好的支持路由功能(實現路由功能的組件叫作 Device),把 1:N 擴展爲N:M (只需要加入若干路由節點)

server爲REP模式,等待消息,client爲REQ模式,向server請求消息。
簡單的例子
server.py

import zmq
import sys
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")
while True:
    try:
        print("wait for client ...")
        message = socket.recv()
        print("message from client:", message.decode('utf-8'))
        input1 = raw_input("請輸入內容:")
        socket.send(input1)
    except Exception as e:
        print '異常:',e
        sys.exit()

client.py

import zmq
import sys
context = zmq.Context()
print("Connecting to server...")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")
while True:
    input1 = raw_input("請輸入內容:")
    if input1 == 'b':
        sys.exit()
    socket.send(input1.encode('utf-8'))
    message = socket.recv()
    print("Received reply: ", message.decode('utf-8'))

1.服務端和客戶端無論誰先啓動,效果是相同的,這點不同於 Socket。
2.在服務端收到信息以前,程序是阻塞的,會一直等待客戶端連接上來。
3.問一答式的。如果 Server 先 send,client 先 rev 是會報錯的。
4.ZMQ 通信通信單元是消息,他除了知道 Bytes 的大小,他並不關心的消息格式。因此,你可以使用任何你覺得好用的數據格式。Xml、Protocol Buffers、Thrift、json 等等。

2.Publish-Subscribe模式(發佈訂閱模型)
廣播所有client,沒有隊列緩存,斷開連接數據將永遠丟失。client可以進行數據過濾。

服務端
server.py

import zmq
import time
import sys
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5555")

while True:
    msg = input("請輸入要發佈的信息:").strip()
    if msg == 'b':   #關閉連接的字符
        sys.exit()
    socket.send(msg.encode('utf-8'))
    time.sleep(1)
  1. 與 Hello World 不同的是,Socket 的類型變成 SOCKET_PUB 和 SOCKET_SUB 類型。
  2. 客戶端需要$subscriber->setSockOpt (ZMQ::SOCKOPT_SUBSCRIBE, $filter);設置一個過濾值,相當於設定一個訂閱頻道,否則什麼信息也收不到。
  3. 服務器端一直不斷的廣播中,如果中途有 Subscriber 端退出,並不影響他繼續的廣播,當 Subscriber 再連接上來的時候,收到的就是後來發送的新的信息了。這對比較晚加入的,或者是中途離開的訂閱者,必然會丟失掉一部分信息,這是這個模式的一個問題,所謂的 Slow joiner。稍後,會解決這個問題。
  4. 但是,如果 Publisher 中途離開,所有的 Subscriber 會 hold 住,等待 Publisher 再上線的時候,會繼續接受信息。

客戶端 (可以開多個客戶端來接收消息)
client.py

import zmq
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5555")   #多個客戶端連接同樣的地址
socket.setsockopt(zmq.SUBSCRIBE,'123'.encode('utf-8'))  # 消息過濾  只接受123開頭的信息
#socket.setsockopt(zmq.SUBSCRIBE,''.encode('utf-8'))  # 接收所有消息
#兩種情況  這裏必須使用一種來 過濾消息 不然無法接受消息
while True:
    response = socket.recv().decode('utf-8');
    print("response: %s" % response)

3.Parallel Pipeline模式(管道模型)
由三部分組成,push進行數據推送,work進行數據緩存,pull進行數據競爭獲取處理。區別於Publish-Subscribe存在一個數據緩存和處理負載。
當連接被斷開,數據不會丟失,重連後數據繼續發送到對端。
在這裏插入圖片描述
server.py

import zmq
import time

context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.bind("tcp://*:5557")

while True:
    msg = input("請輸入要發佈的信息:").strip()
    socket.send(msg.encode('utf-8'))
    print("已發送")
    time.sleep(1)

worker.py

import zmq
context = zmq.Context()
receive = context.socket(zmq.PULL)
receive.connect('tcp://127.0.0.1:5557')
sender = context.socket(zmq.PUSH)
sender.connect('tcp://127.0.0.1:5558')

while True:
    data = receive.recv()
    print("正在轉發...")
    sender.send(data)

client.py

import zmq
context = zmq.Context()
socket = context.socket(zmq.PULL)
socket.bind("tcp://*:5558")

while True:
    response = socket.recv().decode('utf-8')
    print("response: %s" % response)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章