首页 > 解决方案 > ZeroMq:打开的文件太多.. fd 使用量在同一对象上持续增长

问题描述

通过包含 2 个 zeromq 订阅者和 1 个 zeromq 请求套接字的同一个类对象,我在不同的线程中创建对象。我使用 inproc zeromq 套接字并且属于同一个 ZContext。

每次我创建对象时,服务器(运行 Centos 7)系统中打开文件的数量(lsof | wc -l)都会递增。创建第一个对象后,打开文件的数量增加了 300,第二个对象的打开文件数量增加了 304,并且不断增长。

由于我的程序可以在运行时使用这些对象中的许多对象,因此即使我将限制设置为 524288 (ulimit -n),也会导致 zeromq 打开文件过多错误。随着对象数量的增加,每个对象消耗的打开文件限制更多,因为其中一些在 1500 左右。

在运行时,我的程序在创建许多对象并且线程在对象上执行其工作(将消息发送到另一台服务器或客户端)时因打开文件过多错误而崩溃。

我怎样才能克服这个问题?

示例代码:

void Agent::run(void *ctx) {
    zmq::context_t *_context = (zmq::context_t *) ctx;
    zmq::socket_t dataSocket(*(_context),ZMQ_SUB);
    zmq::socket_t orderRequestSocket(*(_context),ZMQ_REQ);//REQ

    std::string bbpFilter = "obprice.1;
    std::string bapFilter = "obprice.2"
    std::string orderFilter = "order";
    dataSocket.connect("inproc://ordertrade_publisher");   
    dataSocket.connect("inproc://orderbook_prices_pub");      
    orderRequestSocket.connect("inproc://frontend_oman_agent");    
    int rc;
    try {         
        zmq::message_t filterMessage;
        zmq::message_t orderMessage;
        rc = dataSocket.recv(&filterMessage);
        dataSocket.recv(&orderMessage); 
        //CALCULATION AND SEND ORDER
        // end:
        return;
    }
    catch(std::exception& e) {
        std::cerr<< "Exception:" << e.what() << std::endl;        
        Order.cancel_order(orderRequestSocket);
        return;
    }
}

标签: c++centos7zeromq

解决方案


我也遇到了这个。我不确定我是否有解决方案,但我看到上下文 ( zmq::context_t) 具有最大数量的套接字。有关zmq_ctx_set更多详细信息,请参阅。此限制默认为ZMQ_MAX_SOCKETS_DFLT1024。

您可能只需要增加您的上下文可以拥有的套接字数量,尽管我怀疑可能会发生一些泄漏(至少在我的情况下)。


更新:

我能够通过套接字选项的组合修复我的泄漏:

  • ZMQ_RCVTIMEO - 如果另一端不存在,我已经在使用它来避免永远等待。我的系统通过只在套接字上发出一个请求然后关闭它来处理这个问题。
  • ZMQ_LINGER - 设置为 0,因此套接字不会等待尝试发送失败的消息。默认行为是无限逗留。这可能是您问题的关键
  • ZMQ_IMMEDIATE - 此选项将消息排队限制为仅完成的连接。没有队列,套接字就没有必要逗留。

我不能确定我是否需要逗留和立即,但它们似乎都适合我的用例;他们可能会帮助你。设置这些选项后,我的打开文件数不会无限增长。


推荐阅读