轻量化高性能跨平台通信中间件ZMQ


轻量化高性能跨平台通信中间件ZMQ

一. 通信中间件 简介

通信中间件是一种用于不同应用程序之间通信的软件。
它们通常用于分布式系统,以便应用程序可以在不同的计算机上运行。
通信中间件可以提供多种通信服务,包括消息传递、远程过程调用和事件通知。

用通俗的话讲,通信中间件就是一个软件或者SDK,它可以让不同的应用程序之间进行通信。

常见的通信中间件有:RabbitMQ、Kafka、RocketMQ、ActiveMQ、ZeroMQ等。 其中,ZeroMQ以轻量化著称。

为什么有了HTTP、TCP、UDP等通信协议,还需要通信中间件呢?

  1. 通信协议的局限性:HTTP、TCP、UDP等通信协议都有自己的局限性,比如HTTP协议是基于请求-响应模式的,不适合实时通信;TCP协议是面向连接的,不适合高并发场景;UDP协议是无连接的,不适合可靠传输。
  2. 通信协议的复杂性:HTTP、TCP、UDP等通信协议的使用复杂,需要开发者自己实现协议的解析、序列化、反序列化等功能。
  3. 通信协议的兼容性:不同的通信协议之间可能不兼容,需要开发者自己实现协议的转换、适配等功能。
  4. 通信协议的性能:HTTP、TCP、UDP等通信协议的性能可能不够高,无法满足高性能、低延迟、高并发的需求。

通信中间件 提供了一整套高效、灵活的通信机制,相比直接使用 TCP 更加适合构建复杂的网络应用。它简化了开发流程,提高了性能,并提供了丰富的特性,使得开发者能够更加专注于业务逻辑而不是底层通信实现。

二. ZeroMQ 简介

ZeroMQ全称是Zero Message Queue(零消息队列),是一个基于消息队列的多线程网络库。

ZMQ是网络通信中新的一层,介于应用层和传输层之间(按照TCP/IP划分)。

ZMQ不是单独的服务,而是一个嵌入式库,它封装了网络通信、消息队列、线程调度等功能,向上层提供简洁的API,应用程序通过加载库文件,调用API函数来实现高性能网络通信。

能够在多种通信模式下工作,如发布/订阅(pub/sub)、请求/响应(req/rep)、推送/拉取(push/pull)等.

支持在多种网络协议上进行通信,包括 TCP、UDP 和 in-process communication(IPC, 进程内通信)。。

  1. 多种通信模式:支持多种通信模式,适用于不同的应用场景,如请求/响应用于 RPC,发布/订阅用于消息广播。
  2. 异步消息处理:使用异步 I/O 模型,可以实现高性能、低延迟的消息传递。
  3. 跨平台支持:支持多种操作系统,包括 Windows、Linux 和 macOS。
  4. 多语言绑定:提供多种编程语言的绑定,如 C、C++、Python、Java、Go 等,使其易于集成到现有项目中。
  5. 简单的 API:提供简单易用的 API,减少了编写网络通信代码的复杂性。

三. pyzmq

pyzmq 是 ZeroMQ 的 Python 库,使得 Python 程序能够使用 ZeroMQ 的功能进行高效的消息传递。

pyzmq 提供了与 ZeroMQ 库一致的 API,并扩展了一些 Python 特有的功能。

1. 安装

可以通过 pip 进行安装:

pip install pyzmq

2. 多种通信协议

(1). TCP(Transmission Control Protocol)

TCP 是一种可靠的、面向连接的传输层协议。使用 TCP 进行通信时,ZeroMQ 提供了一种可靠的消息传递机制,确保消息按顺序且无丢失地传输。

socket.bind("tcp://*:5555")
socket.connect("tcp://localhost:5555")

(2). IPC(Inter-Process Communication)

IPC 是一种用于同一台机器上的进程间通信的协议。使用 IPC 协议,ZeroMQ 可以实现不同进程之间的高效通信。

socket.bind("ipc:///tmp/zmq.sock")
socket.connect("ipc:///tmp/zmq.sock")

(3). In-Process

In-Process(进程内)协议用于同一进程内的线程之间的通信。这种方式速度最快,因为它不涉及网络或进程间通信。

socket.bind("inproc://example")
socket.connect("inproc://example")

(4). PGM(Pragmatic General Multicast)和 EPGM(Encapsulated PGM)

PGM 是一种可靠的多播协议,适用于需要广播消息的应用场景。EPGM 是 PGM 的一种封装版本,允许 PGM 在非原生 PGM 支持的网络上传输。

socket.bind("pgm://eth0;239.192.1.1:5555")
socket.connect("pgm://eth0;239.192.1.1:5555")

(5). UDP(User Datagram Protocol)

UDP 是一种无连接的、不可靠的传输层协议。虽然 ZeroMQ 的原生库不直接支持 UDP,但可以通过某些配置和扩展来实现类似的功能。

(6). TLS(Transport Layer Security)

TLS 是一种用于安全通信的协议。通过加密传输的数据,确保通信的机密性和完整性。ZeroMQ 支持通过 CURVE 加密来实现安全通信,这是 ZeroMQ 提供的一种加密方案。

(7) 示例代码

使用 TCP 协议

服务器端:

import zmq

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")

while True:
    message = socket.recv()
    print(f"Received request: {message}")
    socket.send(b"World")

客户端:

import zmq

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

socket.send(b"Hello")
message = socket.recv()
print(f"Received reply: {message}")
使用 IPC 协议

服务器端:

import zmq

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("ipc:///tmp/zmq.sock")

while True:
    message = socket.recv()
    print(f"Received request: {message}")
    socket.send(b"World")

客户端:

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("ipc:///tmp/zmq.sock")

socket.send(b"Hello")
message = socket.recv()
print(f"Received reply: {message}")

2. 多种通信模式

ZeroMQ 提供了多种通信模式,包括请求/响应(Req/Rep)、发布/订阅(Pub/Sub)、推送/拉取(Push/Pull)、请求/响应(Req/Rep)结合 ROUTER 和 DEALER等。

  • 请求/响应(Req/Rep)用于点对点通信。
  • 发布/订阅(Pub/Sub)用于广播消息。
  • 推送/拉取(Push/Pull)用于任务分发。
  • ROUTER 和 DEALER 套接字可以实现复杂的多对多请求/响应模式。

(1). 请求/响应(Req/Rep)

请求/响应模式是一种点对点通信模式,一个请求者发送请求,一个响应者接收请求并发送响应。

示例代码

请求者(Req):

import zmq

# 创建一个上下文
context = zmq.Context()

# 创建一个响应(REP)套接字
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")

while True:
    # 接收请求
    message = socket.recv()
    print(f"Received request: {message}")

    # 发送响应
    socket.send(b"World")

响应者(Rep):

import zmq

# 创建一个上下文
context = zmq.Context()

# 创建一个请求(REQ)套接字
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")

# 发送请求
socket.send(b"Hello")

# 接收响应
message = socket.recv()
print(f"Received reply: {message}")

(2). 发布/订阅(Pub/Sub)

发布/订阅模式允许一个或多个发布者将消息广播给多个订阅者。订阅者可以根据主题过滤消息。

示例代码

发布者(Publisher):

import zmq
import time

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5556")

while True:
    time.sleep(1)
    socket.send_string("Topic1 Hello")
    socket.send_string("Topic2 World")

订阅者(Subscriber):

import zmq

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5556")

# 订阅特定主题
socket.setsockopt_string(zmq.SUBSCRIBE, "Topic1")

while True:
    message = socket.recv_string()
    print(f"Received: {message}")

(3). 推送/拉取(Push/Pull)

推送/拉取模式适用于任务分发和负载均衡。多个推送者可以将任务发送给多个拉取者,拉取者之间会进行负载均衡。

示例代码

推送者(Push):

import zmq
import time

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

for i in range(10):
    time.sleep(1)
    socket.send_string(f"Task {i}")

拉取者(Pull):

import zmq

context = zmq.Context()
socket = context.socket(zmq.PULL)
socket.connect("tcp://localhost:5557")

while True:
    message = socket.recv_string()
    print(f"Received: {message}")

(4). 请求/响应(Req/Rep)结合 ROUTER 和 DEALER

虽然基本的请求/响应模式是点对点的,但通过使用 ROUTER 和 DEALER 套接字,可以实现多对多的复杂通信模式。ROUTER 套接字可以处理来自多个请求者的消息,而 DEALER 套接字可以将请求分发给多个响应者。

示例代码

ROUTER/DEALER 中介(Broker):

import zmq

context = zmq.Context()

frontend = context.socket(zmq.ROUTER)
frontend.bind("tcp://*:5559")

backend = context.socket(zmq.DEALER)
backend.bind("tcp://*:5560")

zmq.proxy(frontend, backend)

请求者(Client):

import zmq

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

for i in range(5):
    socket.send_string(f"Hello {i}")
    message = socket.recv_string()
    print(f"Received reply {i}: {message}")

响应者(Worker):

import zmq
import time

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.connect("tcp://localhost:5560")

while True:
    message = socket.recv_string()
    print(f"Received request: {message}")
    time.sleep(1)  # 模拟处理时间
    socket.send_string("World")

文章作者: BITBCI
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 BITBCI !
  目录