Understanding and use of zmq module

  I have recently encountered ZeroMQ in the project. The internal implementation is quite complicated. I do n’t have time to understand it in depth. Simply record the usage method, and I will have time to fill the hole. Official guidance document http://zguide.zeromq.org/page:all

  The project mainly uses ZeroMQ to communicate between services on multiple ip hosts. It can also be achieved directly with scoket, but it is more time-consuming and laborious. ZeroMQ is built on the socket and provides a simpler and more powerful API that can be quickly built. Starting from cross-process, cross-ip and other communication networks. Many articles mentioned that sockets can only achieve one-to-one communication. ZeroMQ can achieve many-to-many connections, and there are three modes to choose from, which can be selected and used according to business needs.

  The three communication modes of ZeroMQ are: Request-Reply, Publisher-subscriber, Parallel Pipeline

  Python install zmq module: pip install pyzmq

1. Request-Reply (reply mode)

  Response mode features:

    1. The client makes a request, the server must answer the request, each request is only answered once

    2. The client cannot make another request before receiving the reply

    3. Multiple clients can make requests, and the server can ensure that each client only receives its own reply

       4. What happens if the server is broken or the client is broken?

      If the client is broken, there is no impact on the server. If the client is restarted later, the two parties continue to ask one question and answer, but if the server is broken, some problems may occur, which depends on Under what circumstances the server is disconnected, if the server receives is disconnected after answering the question, then it does not affect, after restarting the server, double send continues to question and answer, but if the server is receiving After the question is broken, there is no time to answer the question. This is a problem. The client who asked the question will not wait for the answer and will wait for the answer. Therefore, no new questions will be sent. After the server restarts, The client did not post any questions, so it kept waiting for questions.

 

 

 Python implements the client and server code as follows:

zmq_server.py

import zmq 


context = zmq.Context () #create context 
socket = context.socket (zmq.REP) #create Response server socket 
socket.bind ( " tcp: // *: 5555 " ) #socket binding, * means this Machine ip, port number is 5555, use tcp protocol communication 

while True: 
    message = socket.recv () 
    print (type (message)) #The received message will also be bytes type (byte) 
    print ( " Received message: { } " .format (message)) 
    socket.send (b " new message " ) #Send message, byte code message

zmq_client.py

#coding:utf-8

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")

socket.send(b"A message")
response = socket.recv()
print(response)

Common data sending APIs are as follows:

# 
送 数据 socket.send_json (data) #data will be serialized by json for transmission (json.dumps) 
socket.send_string (data, encoding = " utf-8 " ) #data is a unicode string, which will be encoded into subsections Then transmit 
socket.send_pyobj (obj) #obj is a Python object, use pickle to serialize and transmit 
socket.send_multipart (msg_parts) # msg_parts, send an iterator sequence composed of multiple messages, each message is a subsection type, 
                                    # such as [b " message1 " , b " message2 " , b " message2 " ] #Receive 
data socket.recv_json 
() 
socket.recv_string () 
socket.recv_pyobj () 
socket.recv_multipart ()

 

2. Publisher-Subscriber (publish-subscribe model)

  Publiser broadcasts messages to all clients, and clients filter messages based on the topic of subscription

 

 

 The Python implementation code is as follows. The publisher publishes two messages. The topic of the first message is client1, which is received by the first subscriber; the topic of the second message is client2, which is received by the second subscriber.

Note that when the subscriber is matched, it is not an exact match. The topic of the message will be matched with the string beginning with client1. If the topic is "client1cient2", it will also be received by the first subscriber

zmq_server.py

#coding:utf-8
import zmq

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5555")
topic = ["client1", "client2"]
while True:
    for t in topic:
        data = "message for {}".format(t)
        msg = [t.encode("utf-8"), data.encode("utf-8")] # The first item in the list is the topic of the message, and the sub filter messages according to the topic 
        print (msg) 
        socket.send_multipart (msg)

zmq_client1.py

#coding:utf-8

import zmq


context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.subscribe("client1")          #订阅主题topic为:client1
socket.connect("tcp://localhost:5555")
msg = socket.recv_multipart()
print(msg)

result:

 

 

zmq_client2.py

import zmq 

context = zmq.Context ()
socket = context.socket (zmq.SUB)
socket.subscribe ("client2") #Subscription topic topic is: client2
socket.connect("tcp://localhost:5555")
msg = socket.recv_multipart()
print(msg) 

result:

3. Parallel Pipeline (parallel pipeline mode)

    The pipeline mode consists of three parts. As shown in the figure below, the leftmost producer generates tasks through push. The consumer in the middle receives the tasks and forwards them. Finally, the result collector receives the results of all tasks. Compared with the publisher-subscriber, there is an additional data cache and processing load part. When the connection is disconnected, the data will not be lost. After the reconnection, the data continues to be sent to the client.

 

 

 Python implements producer, consumer, resultcollector

producer.py

import zmq

context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.bind("tcp://*:5577")
for num in range(2000):
    work_message = {"num": num}
    socket.send_json(work_message)

consumer.py

import random
import zmq
context = zmq.Context()
consumer_id = random.randint(1, 1000)
#接收工作
consumer_receiver = context.socket(zmq.PULL)
consumer_receiver.connect("tcp://localhost:5577")
#转发结果
consumer_sender = context.socket(zmq.PUSH)
consumer_sender.bind("tcp://*:5578")
while True:
    msg = consumer_receiver.recv_json()
    data = msg["num"]
    result = {"consumer_id":consumer_id, "num":data}
    consumer_sender.send_json(result)

resultcollector.py

#coding:utf-8

import zmq

context = zmq.Context()
result_receiver = context.socket(zmq.PULL)
result_receiver.connect("tcp://localhost:5578")
result = result_receiver.recv_json()
collecter_data = {}
for x in range(1000):
    if result['consumer_id'] in collecter_data:
        collecter_data[result['consumer_id']] = collecter_data[result['consumer_id']] + 1
    else:
        collecter_data[result['consumer_id']] = 1
    if x == 999:
        print(collecter_data)

Execution order:

python producer.py
python consumer.py
python resultcollector.py

 

 Reference article:

https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/patterns/pushpull.html 

https://segmentfault.com/a/1190000012010573

 

Guess you like

Origin www.cnblogs.com/silence-cho/p/12657234.html
zmq