我正在尝试评估ZeroMQ以获得更大的监控和数据收集系统。在较小的规模上,一切都很好,但加大负荷和规模似乎有点棘手。
现在我正在使用C#包装器(clrzmq,3.0.0-rc1)来创建发布者和订阅者应用程序。我将Publisher套接字(1个套接字,1个上下文)绑定到1000个端点(localhost +一系列端口),并让订阅者应用程序套接字(再次为1个套接字,1个上下文)绑定到发布者端点。
这有时会起作用,有时也不行(我猜这与过程以某种方式处理的最大套接字数有关)。它似乎取决于我启动应用程序的顺序,但我无法确定。我唯一看到的是讨厌的SEHExceptions,根本不包含任何细节。如果我创建简单的控制台应用程序,我有时会看到低级C ++断言,如:
对我不是很有帮助。在C#包装器中,Context创建失败。它甚至没有机会开始连接甚至创建套接字。我希望通过抛出异常来处理低级ZeroMQ错误,也许我还没有理解如何处理错误。
我现在的问题是:
由于ZeroMQ似乎相当稳定和成熟,我很难相信1000个发布者应该是一个问题。但是,我需要比当前可用的更好的错误支持(除非我完全错过了这里),以便使用ZeroMQ而不是C#。
更新
在进入源代码后,我最终得到zmq_assert(...)
,导致RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info);
。在将原始断言语句转储到控制台之后,这将突然终止应用程序。这似乎有点苛刻,但鉴于它真的无法恢复,可能是最好的选择。但是,一个更好的错误消息不会受到伤害。不是每个人都知道fds.size () <= FD_SETSIZE
的含义。源代码中的注释提供了一些线索,在错误消息中包含该注释会很好。无论如何,鉴于我的应用程序不是一个控制台应用程序,这只留下一个未处理的SEHException,它似乎甚至不包含断言语句或行/文件信息。我想知道我将创建多少其他错误,这将导致其他类似的密码错误。
答案 0 :(得分:3)
在进一步研究之后,似乎默认的套接字数量设置为1024.C#包装器在Context
对象上有一个属性应该能够更改此设置但是它不起作用,至少不如预期的那样。此外,本机zmqlib
在上下文对象上没有此设置。
运行像描述中的设置似乎不可能,至少不使用clrzmq
C#ZeroMQ包装器。我通过在另一台机器上运行500个发布者和在另一台机器上运行另外500个1000个订阅者来解决它。这很好用,没有任何错误。
另一个话题也有点令人失望。当达到最大套接字数时,ZeroMQ会抛出一个无法捕获的异常,导致应用程序突然崩溃。这是一种快速失败的方法,避免任何进一步的数据/状态损坏,但不幸的是,也很少留下导致应用程序死亡的事情的线索。从其他帖子来看,当发生这种情况时,收集验尸数据似乎非常困难。在C#代码中捕获异常似乎不可能或非常困难,并且挂钩到stdout以捕获打印的断言似乎也很难实现(如果我们不是从命令提示符运行,在这种情况下,断言消息在之前打印申请死亡。)
总而言之,当ZeroMQ通过zmq_assert(...)调用终止时,这会在非控制台C#设置中进行低级故障排除和事后分析。希望这是一个极端的例子。并非所有故障模式都会以这种突然的方式导致终止。
答案 1 :(得分:2)
默认的FD_SETSIZE是1024(在MSVC libzmq项目中定义),因此您将在测试用例的大约一半时间内完成此操作。另一个断言就是这样。
将你的libzmq项目中的这个增加到4K或8K,事情应该会更好。
至于assert()调用,肯定是在Windows上太残酷了。在Linux上,这提供了一个不错的堆栈转储和足够的信息来跟踪问题。随意改进断言宏,使其更聪明,例如启动调试器。无论如何,如果你打了一个断言,你就无法合理地继续下去。
当FD设置已满时断言,那可以更好地处理。如果您对C / C ++一无所知,请随时查看代码。我们确实依赖于人们的补丁。
此外,如果您觉得1024太小,请随意在项目中提出这个问题并将补丁发送给我们。
答案 2 :(得分:1)
快速而肮脏地查看此问题表明您为计算机创建了太多套接字连接。从MSDN中查看此link on the max number of sockets。你得到的错误看起来很可疑,因为这可能是你错误的可能来源。
老实说,拥有1000个独立的发布商似乎正在使用zmq解决这个问题。为什么不拥有1个发布者并使用“名称空间”,并让订阅者SUBSCRIBE分配出订阅者获得的消息所需的内容。