【问题标题】:How to send individual messages using ZMQ efficiently in both python and php如何在 python 和 php 中有效地使用 ZMQ 发送单个消息
【发布时间】:2018-09-07 11:59:35
【问题描述】:

我目前有一个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); 没有帮助。

【问题讨论】:

    标签: php python sockets zeromq pyzmq


    【解决方案1】:

    鉴于对任一 code-sn-ps 的每次调用都会生成另一个 Context()-实例,这构成了合理使用资源的反模式。

    对 Zen-of-Zero 的温和阅读很快就会说明主要原因,为什么要构建(半)持久的信号/消息传递层,因为资源分配/释放总是很昂贵,而且留下这么多未终止的实例很快就会耗尽所有可用资源。

    ZeroMQ 工具远非一次性使用。效率与最小化的资源相关开销齐头并进,因此最好重新设计临时创建从未释放的资源池,而是在这些工具需要已经处于活动状态并准备好为广告服务之前准备好所有需要的工具。临时请求。

    需要对产品进行适当的重构。


    虽然documentation reports 一些持久性辅助了作案手法,但在进入这个方向之前,应该仔细审查其成本/收益,因为 Zen-of-Zero 实际上正在考虑为 共享一种相当反模式的任何形式设计实践,加上警告:

    注意

    请务必记住,不小心使用持久性套接字可能会耗尽机器上可用的文件句柄。

    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()
    }
    

    最后说明

    任何应用程序的质量、稳健性和性能都取决于语言和特定语言的 ZeroMQ 绑定在尊重本机 API 和反映使用本机 DLL 服务的最佳实践方面的能力。任何“抽象”和/或“自动化”步骤,会减少设计人员对范围的控制以及在本机 API 级别上其他应有步骤的顺序可能看起来很舒服,但这些也减少了设计健壮和高性能部署的选项,因为某些原生 API 调整选项主要不需要在用户应用程序级别可用,一旦被特定语言的 ZeroMQ 绑定抽象遮蔽。

    【讨论】:

    • 我完全同意,但根据定义,我的系统非常“一次性”。如果我错了,请纠正我,但我真的看不到使用 PHP $_FILE 上传脚本的任何方法?我在许多不同的项目中实施了这种技术:| (只是 PHP)
    • 感谢您的精彩回答。我不太明白persistent_id 这是否意味着如果我在getSocket 中设置标签,然后在带有标签的完全不同的php 线程中再次使用getSocket,它将获得持久套接字?我还认为当对象在 php 脚本结束时死掉时套接字已断开连接 - github.com/mkoppanen/php-zmq/issues/153 ?我也猜想MODE_NOBLOCK 会阻止断开连接杀死发送?
    • 头文件通常保留对 DONTWAITNOBLOCK 两者的定义(通常通过链式别名),所以这更像是一个非功能性变化的品味和传播比任何重要的事情都重要...... :o)
    • Persistencephp 特有的行为,不存在于 native-API 中,因此这里应该多加注意和小心。正如在特定于 php 的语言绑定中非常简要地提到的那样,persistence_ID 应该将生成的对象映射到 "zeromq_socket:[<ZmqSockTYPE>]-[<persistenceID>]" 的某个全局字典中,这似乎是在半持久的php::ZMQ::ZMQContext 实例,如果一切顺利的话。虽然提到了这些功能,但应该在源文件中寻找更多细节,因为这不是原生 API 操作方式,所以询问 PHP-sources
    • Disconnect:表示ZMTP释放。计划的消息应该保留在 ZMQ::ZMQContext 实例的各自内部队列中直到被传递(它们不会在.send()-method 请求返回时立即被调度,可以测试此功能)。所有 ZeroMQ 操作都是异步的,这意味着 ZMQ::ZMQContext-instance 决定事情何时以及如何通过实时传输类路径移动。原生 ZeroMQ API 明确推荐“手动”资源管理,不依赖于任何延迟作用域结束/延迟析构函数调用机制
    猜你喜欢
    • 2021-12-18
    • 2014-04-30
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多