saltstack系列(二)——zmq應答模式

python zeromq介紹

  一、ZeroMQ並非一個對socket的封裝,不能用它去實現已有的網絡協議。python

  二、有本身的模式,不一樣於更底層的點對點通信模式。服務器

  三、有比tcp協議更高一級的協議(固然ZeroMQ不必定基於TCP協議,它也能夠用於進程間和進程內通信)。網絡

  四、改變了通信都基於一對一的鏈接這個假設。socket

zeromq通信模型

  一、請求應答模型tcp

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

  二、發佈訂閱模型spa

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

  三、管道模型server

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

zeromq請求應答模型

  應答模式,就是一問一答,規則有這麼幾條:

   一、 必須先提問,後回答

        二、 對於一個提問,只能回答一次

        三、 在沒有收到回答前不能再次提問

上代碼,服務端: 

#coding=utf-8  

import zmq  
import time  
  
context = zmq.Context()  
socket = context.socket(zmq.REP)  
socket.bind('tcp://127.0.0.1:8000')  
  
while True:  
    message = socket.recv()  
    print 'received request: ' ,message  
      
    time.sleep(1)  
    socket.send('World')  

 客戶端:

#coding=utf-8  
''''' 
你沒法連續向服務器發送數據,必須發送一次,接收一次 
REQ和REP模式中,客戶端必須先發起請求 

'''  
import zmq  
  
context = zmq.Context()  
print 'connect to hello world server'  
socket =  context.socket(zmq.REQ)  
socket.connect('tcp://127.0.0.1:8000')  
  
for request in range(1,10):  
    print 'send ',request,'...'  
    socket.send('hello')  
    message = socket.recv()  
    print 'received reply ',request,'[',message,']'  

說明:

  客戶端老是必須先提問,客戶端提問後,必須等待回答,在收到回答前若是又發出提問,那麼會報錯。  

  zmq.REP是應答方,zmq.REQ是提問方,顯然,咱們能夠有多個提問方,但只能有一個提問方。

問答環節

問題1:應答方和提問方誰先啓動呢?(服務端和客戶端誰先啓動呢?)

   答:誰先啓動均可以,和pub/sub模式同樣

 

問題2:若是服務端斷掉或者客戶端斷掉會產生怎樣的影響?

  答:若是是客戶端斷掉,對服務端沒有任何影響,若是客戶端隨後又從新啓動,那麼兩方繼續一問一答,可是若是是服務端斷掉了,就可能會產生一些問題,這要看服務端是在什麼狀況下斷掉的,若是服務端是在回答完問題後斷掉的,那麼沒影響,重啓服務端後,雙發繼續一問一答,但若是服務端是在收到問題後斷掉了,還沒來得及回答問題,這就有問題了,那個提問的客戶端遲遲得不到答案,就會一直等待答案,所以不會再發送新的提問,服務端重啓後,客戶端遲遲不發問題,因此也就一直等待提問。

 

問題3: 看代碼,服務端根本就沒去區分提問者是誰,若是有兩個提問題的人,如何保證服務端的答案准確的發給那個提問的客戶端呢?

  答:關於這一點,你們沒必要擔憂,zmq的內部機制已經作了保證,提問者必然只收到屬於本身的答案,咱們沒必要去操心zmq是怎麼作到的,你只需關於業務自己便可。

 

如今,咱們把服務端代碼作修改

#coding=utf-8  

import zmq  
import time  
  
context = zmq.Context()  
socket = context.socket(zmq.REP)  
socket.bind('tcp://127.0.0.1:8000')  
  
while True:  
    message = socket.recv()  
    print 'received request: ' ,message  
    time.sleep(1)  
    if message == 'hello':  
        socket.send('World')  
    else:  
        socket.send('success')  
服務端
#coding=utf-8  

import zmq  
  
context = zmq.Context()  
print 'connect to hello world server'  
socket =  context.socket(zmq.REQ)  
socket.connect('tcp://127.0.0.1:8000')  
  
for request in range(1,10):  
    print 'send ',request,'...'  
    socket.send('hello')  
    message = socket.recv()  
    print 'received reply ',request,'[',message,']'  
客戶端1
#coding=utf-8  

import zmq  
  
context = zmq.Context()  
print 'connect to hello world server'  
socket =  context.socket(zmq.REQ)  
socket.connect('tcp://127.0.0.1:8000')  
  
for request in range(1,10):  
    print 'send ',request,'...'  
    socket.send('ok')  
    message = socket.recv()  
    print 'received reply ',request,'[',message,']'  
客戶端2

實際的運行結果如圖:

不難看出,每一個客戶端都收到了只屬於本身的答案 

相關文章
相關標籤/搜索