【问题标题】:ZeroMQ while True does not work forever in python, why?ZeroMQ 虽然 True 在 python 中不能永远工作,为什么?
【发布时间】:2022-01-10 00:59:31
【问题描述】:

我在 Ubuntu 20.04 服务器中有这个脚本,它保存了我通过笔记本电脑定期发送给它的一些数据,但是脚本并没有像它应该做的那样永远运行,即使在使用了 while True 循环之后,因为当我尝试像往常一样连接到服务器我没有得到响应,我必须再次 ssh 到服务器才能运行它然后它才能工作

我的代码是:

import zmq
import time
import json

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")
print("listening on port 5555")
  
while True:
   try:
       message    = socket.recv().decode('UTF-8')
       content    = json.loads(message)
       post_slug  = content['post_slug']
       image_slug = content['image_slug']
       refer      = content['refer']
       links      = content['links']
       result     = f"{content},{post_slug},{image_slug},{refer},{links}"
       socket.send_string(result)
   except Exception as e:
       print(f"could not send data to main server  with error  \n \n {str(e)}")
   time.sleep(1)

【问题讨论】:

  • ...它做了什么?你得到什么错误?一般来说,您的观察结果是什么,而不仅仅是解释(“不会永远运行”)?
  • @Ulrich Eckhardt 没有错误,当我尝试通过端口 5555 连接到服务器时,我知道它停止了,但我没有得到任何回复或确认它已连接
  • 你可以edit你的问题来澄清这一点。这种方式比将各种相关信息放入 cmets 更好。另外,它产生的输出是什么?此外,您提供的信息再次出现同样的问题:“当我尝试连接时......” - 如何确切地?不要让别人猜你在做什么!也就是说,它甚至可以工作一次吗?它的工作频率和时间是多少?脚本产生的输出是什么,例如错误信息?

标签: python-3.x zeromq ubuntu-20.04 pyzmq


【解决方案1】:

Q :
"...当我尝试通过端口 5555 连接到服务器时,我知道它停止了,但我没有得到任何回复或确认它连接“

A:
嗯,
ZeroMQ REQ/REP-session 不容易连接/断开并重新进入循环。

为什么?
ZeroMQ REQ-side 询问(.send()),并希望 REP-side 确实回答(首先使用 .recv() 并发送答案,使用 .send()) .如果这种分布式 FSA 不再遵循两步舞,就会发生无法挽救的相互死锁(迟早......)

作为一个起始模板,这可能有助于解决在.recv()-方法的阻塞形式上不要陷入无休止的状态。

...
try:
    print (                     "INF: REP-side is going to .bind()" )
    socket.bind( "tcp://A.B.C.D:5555" )
    print (                     "INF: REP-side was able to .bind()" )

except:
    print (                     "EXC: REP-side on going to .bind()" )
    exit()

...
while True:
   try:
       print (                     "INF: REP-side is going to .poll()" )
       while 0 == socket.poll( timeout = POLL_WAIT_TIME_MSEC,
                               flags   = zmq.POLLIN
                               ):
             print (               "NOP: REP-side is going to .sleep()" )
             time.sleep( POLL_LOOP_SLEEP_TIME )
             print (               "INF: REP-side is going to .poll() again" )

       print (                     "INF: REP-side is ready to .recv()" )

       content    = json.loads( socket.recv().decode( 'UTF-8' ) )

       print (                     "INF: REP-side is recvd a message" )

       post_slug  = content['post_slug']
       image_slug = content['image_slug']
       refer      = content['refer']
       links      = content['links']
       result     = f"{content},{post_slug},{image_slug},{refer},{links}"

       print (                     "INF: REP-side is ready to .send()" )
       socket.send_string( result )

   except Exception as e:
       print (                     "EXC: something happened", repr( e ) )

   time.sleep(1)

进一步的问题清单:

  • 接收方必须处理能够处理的情况,当(无论出于何种原因).recv() 将面临传入队列中的多部分消息(上面的代码默默地假设这永远不会发生,但处理循环应该是添加,以解决任何此类情况,否则将永远无法保持流程正常工作 - 永远不会有.send(),除非来自.recv()-ed 的所有“尾”帧都已全部完全.recv()-ed)

  • 配置套接字可能有助于使 1 个或多个客户端之间的 { .connect() | .disconnect() } 关系可存活(.setsockopt( zmq.IMMEDIATE, True ), zmq.CONFLATE, ... 和其他属性可能有助于提高连接级别的稳健性和/或性能(如果需要))

  • 最后但同样重要的是,socket_monitor()-instance 能够在需要对连接级事件做出反应/响应时提供额外的监控/信号级别详细信息

【讨论】:

  • 在没有找到任何解决方案后我做了一个 xd,我创建了 cron 作业以每 1 分钟运行一次程序,并且我检查了文件是否已经运行,但如果它不会执行停止它将被执行
猜你喜欢
  • 1970-01-01
  • 2015-12-06
  • 2016-02-08
  • 2016-11-29
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 2022-10-08
  • 1970-01-01
相关资源
最近更新 更多