使用TCP作为传输层的ZeroMQ PUB / SUB模式的奇怪行为

时间:2018-04-13 11:04:50

标签: windows zeromq

为了设计我们的API /消息,我已经对我们的数据进行了一些初步测试:

Protobuf V3消息:

message TcpGraphes {
    uint32 flowId                   = 1;
    repeated uint64 curTcpWinSizeUl = 2; // max 3600 elements
    repeated uint64 curTcpWinSizeDl = 3; // max 3600 elements
    repeated uint64 retransUl       = 4; // max 3600 elements
    repeated uint64 retransDl       = 5; // max 3600 elements
    repeated uint32 rtt             = 6; // max 3600 elements
}

将邮件构建为多部分邮件,以便为客户端添加过滤器功能

使用10个python客户端测试:5个在同一台PC(localhost)上运行,5个在外部PC上运行。 使用的协议是TCP。每秒发送约 200条消息

结果:

  1. 本地客户正在工作:他们收到每条消息
  2. 远程客户端丢失了一些消息(吞吐量似乎受服务器限制为每个客户端1Mbit / s)
  3. 服务器代码(C ++):

    // zeroMQ init
    zmq_ctx = zmq_ctx_new();
    zmq_pub_sock = zmq_socket(zmq_ctx, ZMQ_PUB);
    zmq_bind(zmq_pub_sock, "tcp://*:5559");
    

    每秒钟,循环发送大约200条消息:

    std::string serStrg;
    tcpG.SerializeToString(&serStrg);
    // first part identifier: [flowId]tcpAnalysis.TcpGraphes
    std::stringstream id;
    id << It->second->first << tcpG.GetTypeName();
    zmq_send(zmq_pub_sock, id.str().c_str(), id.str().length(), ZMQ_SNDMORE);
    zmq_send(zmq_pub_sock, serStrg.c_str(), serStrg.length(), 0);
    

    客户端代码(python):

    ctx = zmq.Context()
    sub = ctx.socket(zmq.SUB)
    sub.setsockopt(zmq.SUBSCRIBE, '')
    sub.connect('tcp://x.x.x.x:5559')
    print ("Waiting for data...")
    while True:
        message = sub.recv() # first part (filter part, eg:"134tcpAnalysis.TcpGraphes")
        print ("Got some data:",message)
        message = sub.recv() # second part (protobuf bin)
    

    我们已经查看了PCAP,服务器没有使用可用的全部带宽,我可以添加一些新的用户,删除一些现有的用户,每个远程用户只有&#34;只有&#34;的1Mbit / s的

    我测试了两台PC之间的Iperf3 TCP连接,达到60Mbit / s。

    运行python客户端的PC最后有30%的CPU。 我已经最小化了客户端运行的控制台,以避免打印输出,但它没有效果。

    这是TCP传输层(PUB / SUB模式)的正常行为吗?这是否意味着我应该使用EPGM协议?

    配置:

    • 服务器的Windows XP
    • 用于python远程客户端的Windows 7
    • zmq 4.0.4使用

1 个答案:

答案 0 :(得分:1)

以表现为动力的兴趣?

好的,让我们首先更充分地使用这些资源:

// //////////////////////////////////////////////////////
// zeroMQ init
// //////////////////////////////////////////////////////

zmq_ctx = zmq_ctx_new();

int aRetCODE = zmq_ctx_set( zmq_ctx, ZMQ_IO_THREADS, 10 );

assert( 0 == aRetCODE );

zmq_pub_sock = zmq_socket(  zmq_ctx, ZMQ_PUB );

    aRetCODE = zmq_setsockopt( zmq_pub_sock, ZMQ_AFFINITY, 1023 );
    //                                                     ^^^^
    //                                                     ||||
    //                                 (:::::::::::)-------++++
    // >>> print ( "[{0: >16b}]".format( 2**10 - 1 ) ).replace( " ", "." )
    // [......1111111111]
    //        ||||||||||
    //        |||||||||+---- IO-thread 0
    //        ||||||||+----- IO-thread 1
    //        |......+------ IO-thread 2
    //        ::             :         :
    //        |+------------ IO-thread 8
    //        +------------- IO-thread 9
    //
    // API-defined AFFINITY-mapping

具有更新API的非Windows平台可以触及调度程序详细信息并更好地调整O / S端优先级。

网络?

好的,让我们首先更充分地使用这些资源:

    aRetCODE = zmq_setsockopt( zmq_pub_sock, ZMQ_TOS, <_a_HIGH_PRIORITY_ToS#_> );

将整个基础架构转换为 epgm://

好吧,如果有人希望进行实验并获得有关进行该E2E的保证资源。