学了saltstack有一段时间了,说实话,对于一个python爱好者来说salt源代码真是一个宝藏啊。于是乎去看了源代码,发现所有问题都卡在了底层通信上,在看saltstack之前都不知道有一个这么好的zeromq通信协议。现在就来记录关于zeromq的学习笔记。

zmq是什么:zmq是基于之前协议(tcp,ipc,inproc)开发的并发框架,采用异步IO非阻塞方式,多对多的通信模式,无需在意服务端和客户端的启动顺序。它包含四种通信模式:PAIR/PAIR,REP/REQ,PUB/SUB,PUSH/PULL。其他模式都是基于这四种混合使用的。

PAIR/PAIR:一对一的请求,跟普通socket类似,这种模式一般不会用。

代码如下:

server.py

import zmqimport randomimport sysimport timeport = "5556"context = zmq.Context()socket = context.socket(zmq.PAIR)socket.bind("tcp://*:%s" % port)while True:        socket.send("Server message to client3")        msg = socket.recv()        if msg == 'EOF':                break        print msg        time.sleep(1)

client.py

import zmqimport randomimport sysimport timeport = "5556"context = zmq.Context()socket = context.socket(zmq.PAIR)socket.connect("tcp://localhost:%s" % port)for i in range(5):        msg = socket.recv()        print msg        socket.send("client message to server1")        time.sleep(1)socket.send("EOF")

zmq有个好处,就是无需在意server和client的启动顺序。执行这两个脚本。

REP/REQ:请求应答模式,是多对多模式,这个模式必须遵循一定的顺序,且recv和send是成对存在的。客户端首先必须send一个请求再recv响应,服务端必须recv一个请求再send响应。这种模式可以用于负载均衡。

reqrep_server.py

import zmqimport timeimport sysport = "5556"if len(sys.argv) > 1:        port =  sys.argv[1]        int(port)context = zmq.Context()socket = context.socket(zmq.REP)socket.bind("tcp://*:%s" % port)while True:        #  Wait for next request from client        try:                message = socket.recv()                print "Received request: ", message                time.sleep (1)                  socket.send("World from %s:%s" % ('192.168.79.49',port))        except KeyboardInterrupt:                break

repreq_client.py

import zmqimport sysport = "5556"if len(sys.argv) > 1:        port =  sys.argv[1]        int(port)if len(sys.argv) > 2:        port1 =  sys.argv[2]        int(port1)context = zmq.Context()print "Connecting to server..."socket = context.socket(zmq.REQ)socket.connect ("tcp://localhost:%s" % port)if len(sys.argv) > 2:        socket.connect ("tcp://localhost:%s" % port1)for request in range (1,10):        print "Sending request ", request,"..."        socket.send ("Hello")        #  Get the reply.        message = socket.recv()        print "Received reply ", request, "[", message, "]"

python reqrep_server.py 5555

python reqrep_server.py 5556

python reqrep_client.py 5555 5556

执行这三个命令,请求会均衡的发到两个服务端。