我正在寻找在BSD或MIT许可下发布的Python 2.7替代ZeroMQ的方法。我正在寻找一种支持请求-答复和发布-订阅消息传递模式的东西。如有必要,我可以自己序列化数据。我从Twisted Matrix Labs找到了Twisted,但它似乎需要一个阻塞事件循环,即reactor.run()。我需要一个在后台运行的库,并让我的应用程序在发生某些事件时检查消息。还有其他选择吗?
最佳答案
给nanomsg
,一个ZeroMQ妹妹,尝试-同一个父亲,同一个美女
是的,它已获得MIT / X11许可。
是的,REQ/REP
-允许构建无状态服务的集群以处理用户请求
是的,PUB/SUB
-将消息分发给大量感兴趣的订户
有几个可用的Python绑定
https://github.com/tonysimpson/nanomsg-python(推荐)
https://github.com/sdiehl/pynanomsg
https://github.com/djc/nnpy
nanomsg和ZeroMQ之间的区别
(截至2014/11 v0.5-beta的状态-由nanomsg.org >>> a-click-thru to the original HyperDoc 提供)
发牌
nanomsg库是MIT许可的。这意味着,与ZeroMQ不同,您可以修改源代码,并在不同的许可下(作为专有产品等)重新发布源代码。有关许可的更多原因,请参见here。
POSIX合规
ZeroMQ API虽然是在BSD套接字API上建模的,但与该API并不完全匹配。 nanomsg旨在完全符合POSIX。
套接字表示为int,而不是void指针。
在ZeroMQ中已知的上下文在nanomsg中不存在。这意味着更简单的API(可以在一个步骤中创建套接字),以及可以在单个过程中使用该库在不同模块之间进行通信(请考虑以不同语言实现的插件相互交流)。可以在here中找到更多讨论。
发送和接收功能(nn_send
,nn_sendmsg
,nn_recv
和nn_recvmsg
)完全匹配POSIX语法和语义。
实现语言
该库是用C而不是C ++实现的。
从用户的角度来看,这意味着不依赖C ++运行时(libstdc ++或类似程序),这在受限和嵌入式环境中可能很方便。
从nanomsg开发人员的角度来看,它使生活更轻松。
由于使用了侵入式容器而不是C ++ STL容器,因此内存分配的数量大大减少了。
以上还意味着更少的内存碎片,更少的缓存未命中等。
可以在here和here中找到有关C vs. C ++主题的更多讨论。
可插拔传输和协议
在ZeroMQ中,没有用于插入新传输(例如WebSocket,DCCP,SCTP)和新协议(与REQ/REP
,PUB/SUB
等对应的协议)的正式API。因此,自2008年以来,没有添加任何新传输。要么实施了新协议。正式的内部传输API(请参阅transport.h
和protocol.h
)旨在减轻该问题,并作为创建和试验新的传输和协议的基础。
请注意,这两个API仍然是新的,将来可能会进行一些调整,以使其可用于多种情况。
nanomsg实现了新的SURVEY
协议。这个想法是向多个对等方发送一条消息(“调查”),并等待所有对等方的响应。有关更多详细信息,请查看文章here。同时查看here。
在金融服务中,通常使用“将消息从任何人传递给其他人”的消息传递。为了解决这个用例,在nanomsg中实现了一个新的BUS
协议。检查详细信息here。
线程模型
我在ZeroMQ中所做的最大架构错误之一是其线程模型。每个单独的对象仅由单个线程管理。这对于由工作线程处理的异步对象非常有效,但是,对于由用户线程管理的对象则成为麻烦。该线程可用于在任意时间段内执行不相关的工作,例如一个小时,然后在此期间它所管理的对象完全卡住。不幸的结果是:无法实现以REQ/REP
协议重发的请求,在应用程序执行其他工作时未应用PUB/SUB
订阅等。在nanomsg中,对象未紧密绑定到特定线程,因此不存在这些问题。
ZeroMQ中的REQ
套接字不能真正在实际环境中使用,因为如果由于服务故障或类似原因导致消息丢失,它们将卡住。用户必须改用XREQ
并实现自己重试的请求。使用nanomsg,重试功能内置在REQ
套接字中。
在nanomsg中,REQ
和REP
均支持取消正在进行的处理。只需发送一个新请求而无需等待答复(对于REQ
套接字),或获取一个新请求而无需答复上一个请求(对于REP
套接字)。
在ZeroMQ中,由于其线程模型,“绑定先连接然后连接”场景不适用于Inproc传输。它以nanomsg固定。
由于类似的原因,自动重新连接不适用于ZeroMQ中的过程内传输。这个问题在nanomsg中也得到解决。
最后,nanomsg尝试使nanomsg套接字具有线程安全性。虽然仍然不鼓励从多个线程并行使用单个套接字,但是在这种情况下ZeroMQ套接字随机失败的方式被证明是痛苦且难以调试的。
状态机
nanomsg库内部的内部交互被建模为一组状态机。目的是避免出现在ZeroMQ中无法理解的关闭机制,从而使库的开发更加容易。
有关更多讨论,请参见here和here。
IOCP支持
ZeroMQ中的一个长期存在的问题是,即使在Windows平台上它是二等公民,它在内部也使用BSD套接字API。相反,适当地使用IOCP将需要对代码库进行重大重写,因此尽管进行了多次尝试,却从未实现过。 IOCP应该具有更好的性能特征,更重要的是,它允许使用其他传输机制,例如不能通过BSD套接字API访问的NamedPipes。由于这些原因,nanomsg在Windows平台上内部使用IOCP。
电平触发的轮询
ZeroMQ的一个使用户感到困惑的方面之一是能够通过使用ZMQ_FD
文件描述符将ZeroMQ套接字集成到外部事件循环中。造成混淆的主要原因是描述符是边缘触发的,即仅在之前没有消息且有新消息到达时才发信号。 nanomsg使用级别触发的文件描述符来代替,它只是在何时有消息可用时发出信号,而不管它过去是否可用。
路由优先级
nanomsg实现出站流量的优先级。您可以决定优先将邮件路由到特定的目的地,只有在主邮件不可用时才回退到备用目的地。
有关更多讨论,请参见here。
TCP传输增强
TCP传输略有增强。连接时,可以选择指定用于连接的本地接口,如下所示:nn_connect (s, "tcp://eth0;192.168.0.111:5555")
。
异步DNS
DNS查询(例如,将主机名转换为IP地址)以异步方式完成。在ZeroMQ中,此类查询是同步完成的,这意味着当DNS不可用时,整个库(包括未使用DNS的套接字)都将挂起。
零复制
虽然ZeroMQ提供了“零拷贝” API,但它不是真正的零拷贝。而是“零复制直到消息到达内核边界”。从那时起,将像标准TCP一样复制数据。另一方面,nanomsg旨在支持真正的零复制机制,例如RDMA
(CPU旁路,直接内存到内存复制)和shmem
(通过使用共享内存在同一盒子上的进程之间传输数据) )。零拷贝消息传递的API入口点是nn_allocmsg
和nn_freemsg
函数,以及传递给send / recv函数的NN_MSG
选项。
高效的订阅匹配
在ZeroMQ中,简单尝试用于存储和匹配PUB / SUB订阅。订阅机制旨在用于最多10,000个订阅,其中简单的Trie效果很好。但是,有些用户使用多达150,000,000个订阅。在这种情况下,需要更有效的数据结构。因此,nanomsg使用的是Patricia trie的内存有效版本,而不是简单的trie。
有关更多详细信息,请检查此article。
统一缓冲区模型
ZeroMQ具有奇怪的双重缓冲行为。传出和传入数据都存储在消息队列和TCP的tx / rx缓冲区中。例如,这意味着如果要限制传出数据量,则必须同时设置ZMQ_SNDBUF
和ZMQ_SNDHWM
套接字选项。鉴于两者之间没有语义上的差异,nanomsg仅使用TCP(或等效的)缓冲区来存储数据。
可伸缩性协议
最后,在哲学层面上,nanomsg旨在实现不同的“可扩展性协议”,而不是成为通用的网络库。特别:
不同的协议完全分开,您不能将REQ
套接字连接到SUB
套接字或类似套接字。
每个协议都体现了具有明确定义的先决条件的分布式算法(例如,在REQ/REP
情况下,“服务必须是无状态的”)并保证(如果REQ
套接字保持活动,则请求将最终得到处理)。
部分故障由协议处理,而不由用户处理。实际上,它对用户是透明的。
协议的规范位于/ rfc子目录中。
目标是通过IETF标准化协议。
没有通用的类似UDP的套接字(ZMQ_ROUTER
),您应该使用L4协议来实现这种功能。
关于message-queue - 是否有BSD或MIT许可下发布的Python 2.7替代品ZeroMQ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26946521/