如何在 python 和 php 中有效地使用 ZMQ 发送单独的消息

How to send individual messages using ZMQ efficiently in both python and php

我目前有一个PHP函数:

function sendLocalSocket($message, $port){
    $context = new ZMQContext();
    $socket = $context->getSocket(ZMQ::SOCKET_PUSH);
    $socket->connect("tcp://127.0.0.1:$port");
    $socket->send($message);
}

和一个python函数:

def create_local_socket(port, pull=False):
    context = zmq.Context()
    if pull:
        # for receiving socket messages
        socket = context.socket(zmq.PULL)
        socket.bind("tcp://127.0.0.1:%d" % port)
    else:
        # for sending socket messages
        socket = context.socket(zmq.PUSH)
        socket.connect("tcp://127.0.0.1:%d" % port)
    return socket

然后发送消息 create_local_socket(port).send_json()

不幸的是,这两个函数中的任何一个在快速连续调用时开始急剧挂起并减慢我系统的其余部分。

我一直在考虑如何为永不终止的 python 脚本保持套接字打开,但不幸的是 PHP 这是在文件上传后调用的。

问题是这些函数被任意调用 - php 脚本每次上传使用相同的端口,但 python 脚本使用不同的端口(尽管重复使用)。

我知道 php 挂起是因为 python ZMQ 侦听器记录了 current time - the time the file was uploaded 这需要越来越长的时间,直到上传积压消失。我也知道侦听器脚本没有挂起,在记录接收文件后需要 0.2 秒。 (但这实际上是一个积压日志!)

我觉得答案是保持这些联系。


编辑 1:

尝试:$context = new ZMQContext(1, true); 没有帮助。

鉴于每次调用 code-snippets 中的任何一个都会生成另一个 Context()-实例,这构成了一个合理使用的 anti-pattern资源。

对 Zen-of-Zero 的温和阅读将很快显示主要原因,为什么构建(半)持久信号/消息传递层是可行的方法,因为资源分配/解除分配总是很昂贵而且离开这么多 un-terminated 个实例很快就会耗尽可用资源。

ZeroMQ 工具远未用作 one-shot 一次性工具。效率与最小化的 resources-related 开销密切相关,因此确实最好 re-design ad-hoc 创建永不释放的资源池,而是在这些工具需要已经处于活动状态之前准备好所有需要的工具,并且准备好处理 ad-hoc 请求。

产品到期 re-factoring 需要很长时间才能完成。


虽然 documentation reports some persistence aided modus-operandi, one ought carefully review its costs/benefits before going into this direction, as Zen-of-Zero is actually considering any sort of sharing a rather anti-pattern for 设计实践,加上警告:

备注

重要的是要记住,不小心使用持久套接字 会耗尽 机器上可用的 file-handles。

function sendLocalSocket( $message,                 //  IS to be get delivered
                          $port                     // WAS reported to be
                          ){                        //     all the time the same 
    $context = new ZMQContext( 2, true );           // MAY try persistent CTX
    $socket = $context->getSocket( ZMQ::SOCKET_PUSH,
                                  "persistLoggerID" // MAY use persistent SOCK
                                   );
    $socket->connect(    "tcp://127.0.0.1:$port" ); // MAY use less expensive TC
    $socket->send(       $message,
                          ZMQ::MODE_NOBLOCK         // USE non-blocking mode
                          );
    $socket->disconnect( "tcp://127.0.0.1:$port" ); // USE .disconnect()
}

最后的笔记

任何应用程序的质量、稳健性和性能取决于语言和 language-specific ZeroMQ-binding 能够尊重原生 API 并反映 best-practices 进化的程度使用原生 DLL-services。任何 "abstraction" and/or "automated" 步骤,减少了设计者对 native-API 级别上其他应有步骤的范围和顺序的控制可能看起来很舒服,但这些也减少了选项用于设计稳健的 high-performance 部署,因为一些 native-API 调整选项不需要主要在 user-application 级别可用,一旦 shaded-out 被 language-specific ZeroMQ-binding 抽象。