Majordomo经纪人吞吐量测量

use*_*878 5 sockets distributed distributed-computing zeromq

我正在测试majordomo经纪人的吞吐量.随github上的majordomo代码附带的test_client.c发送同步请求.我想测试majordomo代理可以实现的最大吞吐量.规范(http://rfc.zeromq.org/spec:7)表示它每秒可以切换多达一百万条消息.

首先,我更改了客户端代码以异步发送100k请求.即使在所有套接字上的HWM设置得足够高并且将TCP缓冲区增加到4 MB之后,我也会观察到三个并行运行的客户端丢包.

所以我改变了客户端一次发送10k个请求,然后为它收到的每个回复发送两个请求.我选择10k是因为这允许我并行运行多达十个客户端(每个发送100k消息)而不会丢失任何数据包.这是客户端代码:

#include "../include/mdp.h"
#include <time.h>
int main (int argc, char *argv [])
{
    int verbose = (argc > 1 && streq (argv [1], "-v"));
    mdp_client_t *session = mdp_client_new (argv[1], verbose);
    int count1, count2;
    struct timeval start,end;
    gettimeofday(&start, NULL);
    for (count1 = 0; count1 < 10000; count1++) {
        zmsg_t *request = zmsg_new ();
        zmsg_pushstr (request, "Hello world");
        mdp_client_send (session, "echo", &request);
    }
    for (count1 = 0; count1 < 45000; count1++) {
        zmsg_t *reply = mdp_client_recv (session,NULL,NULL);
        if (reply)
        {
            zmsg_destroy (&reply);
            zmsg_t *request = zmsg_new ();
            zmsg_pushstr (request, "Hello world");
            mdp_client_send (session, "echo", &request);
            request = zmsg_new ();
            zmsg_pushstr (request, "Hello world");
            mdp_client_send (session, "echo", &request);
        }
        else
            break; //  Interrupted by Ctrl-C
    }

    /* receiving the remaining 55k replies */
    for(count1 = 45000; count1 < 100000; count1++)
    {
        zmsg_t *reply = mdp_client_recv (session,NULL,NULL);
        if (reply)
        {
            zmsg_destroy (&reply);
        }
        else
        break;
    }
    gettimeofday(&end, NULL);
    long elapsed = (end.tv_sec - start.tv_sec) +((end.tv_usec - start.tv_usec)/1000000);
    printf("time = %ld\n", elapsed);
    printf ("%d replies received\n", count1);
    mdp_client_destroy (&session);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在同一台机器上运行了代理,工作人员和客户端.这是记录的时间:

number of clients in parallel 
(each client sends 100k )                           Time elapsed (seconds)

1                                                   4                

2                                                   9

3                                                   12

4                                                   16

5                                                   21

10                                                  43
Run Code Online (Sandbox Code Playgroud)

因此,对于每100k请求,经纪人大约需要4秒钟.这是预期的行为吗?我不确定如何每秒实现百万条消息.

最近更新:

我想出了一种提高系统吞吐量的方法:

  1. 两个经纪人而不是一个.其中一个代理(broker1)负责将客户端请求发送给工作者,另一个代理(broker2)负责将工作者的响应发送给客户端.

  2. 工人向经纪人1登记.

  3. 客户端生成唯一ID并向broker2注册.

  4. 除了请求,客户端还将其唯一ID发送到broker1.

  5. Worker从请求中提取唯一的客户端ID,并将其响应(以及必须向其发送响应的客户端ID)发送到broker2.

现在,每100k请求大约需要2秒而不是4秒(使用单个代理时).我在代理代码中添加了gettimeofday调用来测量代理本身添加了多少延迟.

这是我记录的内容

  1. 100k请求(总时间:~2秒) - >经纪人添加的延迟为2秒
  2. 200k请求(总时间:~4秒) - >经纪人添加的延迟为3秒
  3. 300k请求(总时间:~7秒) - >经纪人添加的延迟为5秒

因此,大部分时间都花在代理代码中.有人可以建议如何改善这一点.

And*_*ron 0

最大吞吐量受代理的最大吞吐量限制,但也受工作线程的最大吞吐量限制。

在我看来,你只开始了一名工人。如果您仔细阅读 Majordomo 协议规范,它表示代理应该能够每秒切换数百万条消息,但它并不能保证单个工作人员每秒可以处理数百万条请求。

鉴于工作人员一次仅处理一个请求,并与工作人员使用完全同步的对话(代理在收到回复之前不会发送另一个请求),因此不可能通过单个工作人员充分利用代理,或者甚至是单个工作人员:在回复和下一个请求之间执行与代理的完整网络往返,因此工作人员大部分时间都在等待。

对于初学者,您应该尝试添加更多工人:-)

编辑:快速演示。

我使用 Majordomo 模式的 Python 实现和 ZeroMQ 运行了一个 echo 服务。当然,这是 Python 代码,将进行完整的错误检查,而 C 版本应该快得多,但它显示了多个工作人员响应回复的影响。

测试设置:

  1. 1 名客户
  2. 客户端一次最多发送 1000 个未完成的请求(最初发送 1000 个,然后客户端每次收到响应时发送一个新请求);
  3. 客户端总共发送了100,000个请求;

结果:

  • 使用 1 个工作线程,客户端在 13.6 秒内获得 100,000 个回复(约 7300 RPS)。
  • 使用 2 个工作人员,客户端在 8.0 秒内获得 100,000 个回复(约 12500 RPS)。
  • 使用 3 个工作线程,客户端在 7.8 秒内获得 100,000 个回复(约 13000 RPS)。

使用更多客户端将在代理中产生更好的吞吐量,因为它将在多个套接字上执行 I/O,但计算总代理吞吐量并不那么容易,因此我将让您测量它。