想象一下以下代码:
import threading, zmq, time
context = zmq.Context()
receivers = []
poller = zmq.Poller()
def thread_fn(number: int):
sender = context.socket(zmq.PUSH)
sender.connect("tcp://localhost:%d" % (6666 + number))
for i in range(10):
sender.send_string("message from thread %d" % number)
for i in range(3):
new_receiver = context.socket(zmq.PULL)
new_receiver.bind("tcp://*:%d" % (6666 + i))
poller.register(new_receiver, zmq.POLLIN)
receivers.append(new_receiver)
threading.Thread(target=lambda: thread_fn(i), daemon=True).start()
while True:
try:
socks = dict(poller.poll())
except KeyboardInterrupt:
break
for i in range(3):
if receivers[i] in socks:
print("%d: process message %s" % (i, receivers[i].recv_string()))
time.sleep(0.2) # 'process' the data
线程发送一些不间断的消息,这些消息以相应的PULL
- 套接字的随机顺序到达,然后被“处理”。
Note:
通常会连接到一个PULL
- 套接字,但此示例打算提供多个接收套接字。
输出是:
0: process message message from thread 0
1: process message message from thread 1
0: process message message from thread 0
1: process message message from thread 1
2: process message message from thread 2
0: process message message from thread 0
1: process message message from thread 1
2: process message message from thread 2
....
现在我想从示例中的所有套接字中读取,但我想优先一个套接字。
即:我希望输出为:
0: process message message from thread 0 <-- socket 0 processed first
0: process message message from thread 0
0: process message message from thread 0
0: process message message from thread 0
0: process message message from thread 0
1: process message message from thread 1
1: process message message from thread 1
2: process message message from thread 2
1: process message message from thread 1
2: process message message from thread 2
....
当然我可以用timeout=0
分别轮询套接字,但我想确定ZeroMQ不会为我做这个。
So the questions are:
Q1:
是否有其他方式(除了内置-in .poll( timeout )
)
以确保我在 等待消息之前从一个插槽首先
读取消息在其他插座上?
Q2:
已知最佳做法是否可以手动执行?
答案 0 :(得分:3)
欢迎来到(托管)-chaos的狂野世界,
A1:
是TL;DR
在最近的API / python包装中检查zmq.select()
A2:
是 {{1}必须做一部分严格可靠的系统设计
为了TL;DR
,系统设计应该保持灵活性,不仅要处理上述优先级划分,还要提供严格的方法来强制处理远程故障,以符合(只是乐观地)预期作案手法。
这是什么意思?
如果假定的行为是通过一些简单易懂的实现主要语法构造的部分对齐来实现的,那么这个想法就是这样的:
Q2
在您忘记拥有强大计划B 的那一刻,您的系统架构努力创造的任何好处都会丢失 - 如何处理阻塞状态,丢失消息,死对手FSA流程,DoS-攻击,只是一个有故障的远程网卡,突然用虚假和大量的字节流量向你的入站接口喷射,所有的噩梦都可能出现在你的控制之外。
这意味着,仔细规划如何在一个案例中生存,第一组套接字开始用如此多的消息(处理任务)“喂”你的接收器,你“永远”不会从HI-PRIO部分退出。
如果仍然没有说明问题,让我提醒一下伟大的系统设计,为了这个目的而引入麻省理工学院的一个由Ms. Margaret HAMILTON, {{{}} {{{{{ {3}} 确实幸免于事件的“无限攻击”,工程人员没有预料到,但在现实生活中确实发生过,更糟糕的是,在Eagle降落期间(月球上的月球模块 - 整个旅程中第二个最关键的阶段“那里和后面”。
从汉密尔顿女士团队的智能设计确实拯救了美国最负盛名的阿波罗计划的那一刻和全部荣耀,并不是一种夸张的说法。
# --------------------------------------------------------
# FIRST scan all HI-PRIO socket(s) for incoming messages:
while true:
# process 'em first, based on a ZeroMQ-socket's behaviour-fixed ordering
...
break
# --------------------------------------------------------
# NEXT scan all LO-PRIO socket(s) for incoming messages:
while true:
# process 'em, again, based on a ZeroMQ-socket's behaviour-fixed ordering
...
break
的当前ZeroMQ
包装为此目的提供了一个工具,一个 python
类,一旦得到应有的注意,可以保存您的设计目标,并为添加可靠性驱动的功能提供空间,包括。对优先权/资源情况发生冲突采取后备逃避策略。
Poller()
# ------------------------------------------------------------
# Initialize separate engines for polling set(s)
HiPRIOpoller = zmq.Poller()
LoPRIOpoller = zmq.Poller()
# ------------------------------------------------------------
# Associate
HiPRIOpoller.register( socket_0_pull, zmq.POLLIN ) # 0:
LoPRIOpoller.register( ... , zmq.POLLIN ) # 1:
LoPRIOpoller.register( ... , zmq.POLLIN ) # 2:
...
# ------------------------------------------------------------
# Detect, who is waiting in front of the closed door
aListOfHiPRIOevents = HiPRIOpoller.poll( timeout = 0.200 ) # 200 [us]
aListOfLoPRIOevents = LoPRIOpoller.poll( timeout = 0 ) # no wait at all
# ------------------------------------------------------------
# Now AFTER you have a COMPLETE view what is waiting there
# one
# CAN & SHALL ADAPT order / scope of event-handling,
# IMMUNE to infinite-PRIO-event-flow.
...
# ------------------------------------------------------------
方法会返回准备好处理的 Poller.poll()
事件。这是 list
形式的元组列表,其中第一个元素是( socket, event )
,第二个元素是轮询事件掩码{ a-0MQ-Socket-instance | integer-system-native-fd }
。通常将其称为 ( POLLIN, POLLOUT )
,将元组列表转换为 aDictOfEVENTs = dict( aPoller.poll() )
的映射,如果有人愿意的话。
最后,
结语:向玛格丽特·哈米尔顿及其麻省理工学院团队致敬
如果所有的故事都不能激发我们的想法,那么玛格丽特的勇敢努力已经教会了我们很多关于专业系统设计的知识。可以从这个真正开创性的时代中学到很多东西 - 更多关于
愉快和愉快高兴的是,让我分享白宫关于公平与放松的新闻。玛格丽特·哈米尔顿最近获得总统自由勋章的光荣时刻。
在这种背景下,人们可能会考虑历史上的必要性来比较NASA汉密尔顿公司的团队产品中发现的
毫不妥协的卓越只是卓越。我亲爱的汉密尔顿夫人,我的帽子已经升起了。
让你的启示告诉我们,凡人,更好的前进方式。