【问题标题】:ZMQ Router Req pattern issuesZMQ 路由器请求模式问题
【发布时间】:2019-08-06 04:18:51
【问题描述】:

我正在尝试对工作负载进行动态负载平衡。为此,我使用了 Req-Router 模式。

但目前它只是挂起,而不是任何消息通过。

这是我的工作负载生成器代码 (server.py):

import zmq

address = "ipc:///path/to/named/socket.sock"

socket = zmq.Context().socket(zmq.ROUTER)
socket.bind(address)

for i in range(1000):
    addr,_,resp = socket.recv_multipart()
    print(resp)
    socket.send_multipart([addr, b'', "Ping: " + str(i)])

还有我的客户代码(Client.java):

public static void main(String[] args) throws Exception {
        String address = "/path/to/named/socket.sock";

        System.out.println("CLIENT: Parsed Address: " + address);

        ZMQ.Context context = ZMQ.context(1);
        ZMQ.Socket socket = context.socket(SocketType.REQ);

        address = "ipc://" + address;
        socket.connect( address );
        System.out.println("CLIENT: Connected to " + address);
        for(int i = 0; i < 1000; i++){
            socket.send("Ping " + i);
            System.out.println("CLIENT: Sent.");
            String rep = new String(socket.recv());
            System.out.println("Reply " + i + ": " + rep);
        }
        socket.close();
        context.term();
    }
}

问题是这将打印出Client: Sent,但在另一端,服务器将永远不会打印出任何内容。

我有一个基本的 python 客户端:

import zmq
from sys import argv

print("CLIENT: pinging")
"""Sends ping requests and waits for replies."""
context = zmq.Context()
sock = context.socket(zmq.REQ)
print("CLIENT: Binding to ipc://"+argv[-1])
sock.bind("ipc://"+argv[-1])
print('bound')
for i in range(1000):
    sock.send('ping %s' % i)
    rep = sock.recv()  # This blocks until we get something
    print('Ping got reply:', rep)

在我看来,这与 java 客户端的作用相同(尽管我不认为我遗漏了什么)。

任何帮助将不胜感激!

【问题讨论】:

  • 在 python 端、java 端使用的 ZeroMQ 的确切版本是什么?
  • @user3666197 它们是 python:4.3.1 和 java:4.1.7 版本,所以我猜这可能会导致问题?
  • 您也可以发布 uname -a @Cjen1 吗?谢谢。
  • @user3666197 Linux 1e1b6a3d14de 4.15.0-55-generic #60-Ubuntu SMP Tue Jul 2 18:22:20 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux 此外,每次绑定套接字时,它都会得到755,这可能会导致问题,因为可能位于另一个命名空间(不同容器)中的 java 进程无法写入它。但是,同一容器中的 python 代码可以正常工作。

标签: java python zeromq


【解决方案1】:

ipc:// TRANSPORT-CLASS 有一些特殊之处:

ipc:// 传输类的工作还有一些附加条件:

  • 系统必须提供 UNIX 域套接字
  • ipc:// transport-class AccessPoint-地址说明符必须是
  • ipc:// transport-class AccessPoint-地址说明符必须符合有效的 O/S 文件系统路径语法规则(绝对路径和 @ -abstract-namespace 端点也受到其他约束)
  • ipc:// transport-class AccessPoint-address-endpoint 必须已经在操作系统命名空间中创建,方法是将其分配给具有成功 .bind() 的套接字
  • ipc:// transport-class AccessPoint-address-endpoint 必须是可写的进程拥有调用Context()-instance (容器对于资源隔离都是可疑的和 resource-proxy/abstraction-provisioniong,它们不允许访问实际的托管 O/S 资源,就好像这些通常由在“隔离”的抽象范围“外部”照常运行的类似进程使用- 容器。

下一步:找出根本原因以便能够继续前进

即使您上面的代码使用.recv()-s 的阻塞模式并且没有明确测试任何潜在的错误状态,隔离根本原因的第一步现在是设置相同的@ 987654334@ 使用 tcp:// 传输类来区分否则不可重现的碰撞是否与传输类的选择有关,或者它是否具有其他一些根本原因。

还应该包括公平的资源管理步骤,以便在进程退出之前优雅地释放资源(不谈论强制终止进程的影响,即挂起资源并在重新运行时不允许重用它们预期的代码):

  • 显式aSocketINSTANCE.setsockopt( ZMQ_LINGER, 0 )

  • 显式aSocketINSTANCE.{ close(), .unbind() }

  • 显式aContextINSTANCE.term()

使用基于ZMQ_IMMEDIATE{UID|PID|GID} 的进程的访问过滤可能仍然需要一些额外的预防措施和性能或安全调整,这些进程可能和可以.bind()/.connect(),现在已弃用并使用(最初的“用于 tcp” -only) ZAP-API 服务,仅举几个进一步的设计改进方向。

结语:

不同的包装器可能不仅使用不同的 ZeroMQ 版本,而且有不同的资源处理策略。因此,python-one 可以工作,而 java-one 不需要。例如,.getsockopt( ZMQ_USE_FD ) 可能会根据包装器的作者设计决策显示不同的输出。


如果有人想阅读更多关于 ZeroMQ 内部结构 here 的信息,或者只是想从轨道高的角度了解"ZeroMQ Hierarchy in less than a Five Seconds" 中的一般视图,请随时点击并收集更多详细信息从符合零之禅规则的安逸生活的片断体验。

【讨论】:

  • 谢谢,我在网上找不到太多关于 ipc 的明确文档,所以这是完美的! (甚至在指南中)
  • 永远欢迎@Cjen1 随意使用 StackOverflow 上收集的更多资源,但也要注意 v3.x 中的某些行为和一些默认值从 v2.x 发生变化,并且进一步随着最近的大师们入侵曾经健全和水晶般清晰的零之禅领域,在 v4.x 中进行了扩展。向 ZeroMQ 之父 Martin Sustrik 致敬,我们可以从他身上学到很多东西。
猜你喜欢
  • 1970-01-01
  • 2017-10-08
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多