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

实际的运行结果如图:

不难看出,每一个客户端都收到了只属于本身的答案 

相关文章
相关标签/搜索