Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C ZMQ Multi-part flusher:您是否可以在不全部读取的情况下获取通过ZeroMQ接收的多部分消息中的部分总数?_C_Networking_Zeromq_Distributed System_Low Latency - Fatal编程技术网

C ZMQ Multi-part flusher:您是否可以在不全部读取的情况下获取通过ZeroMQ接收的多部分消息中的部分总数?

C ZMQ Multi-part flusher:您是否可以在不全部读取的情况下获取通过ZeroMQ接收的多部分消息中的部分总数?,c,networking,zeromq,distributed-system,low-latency,C,Networking,Zeromq,Distributed System,Low Latency,我正在使用C语言中的ZeroMQ使用多部分消息传递实现一个简单的REQ-REP模式。我的大多数邮件都有严格的4个部分(来回),只有少数例外。为了实施该规则,我需要确定接收到的多部分消息的部分总数。知道是不是 Q:有人能告诉我如何找到这些信息吗 对 Q:是否有合适的“冲洗器”功能/方法 是和否: 在v4.3.1之前的ZeroMQ v2.x中,没有对“flusher”的显式API调用 ZeroMQ设计所提供的低延迟智能消息传递的美丽和力量建立在一个精心打造的Zero理念之上:始终偏好性能而非舒适性—

我正在使用C语言中的ZeroMQ使用多部分消息传递实现一个简单的
REQ-REP
模式。我的大多数邮件都有严格的4个部分(来回),只有少数例外。为了实施该规则,我需要确定接收到的多部分消息的部分总数。知道是不是 Q:有人能告诉我如何找到这些信息吗

Q:是否有合适的“冲洗器”功能/方法

是和否:

在v4.3.1之前的ZeroMQ v2.x中,没有对“flusher”的显式API调用

ZeroMQ设计所提供的低延迟智能消息传递的美丽和力量建立在一个精心打造的Zero理念之上:始终偏好性能而非舒适性——正如零拷贝、零保修和其他范例所表明的那样

幼稚的(我忍受了很多痛苦,将其琐碎化为使用一个基本的阻塞recv()…)“冲洗器”必须一直运行,直到
ZMQ\u RCVMORE
没有标记“超出”多帧最后消息的任何部分(或者
ZMQ\u msg\u more()==0
也符合相同)。尽管如此,所有这些操作都只进行指针处理,没有数据从RAM中“移动/复制/读取”,只有指针被分配,因此它确实既快速又高效:

int    more;
size_t more_size = sizeof ( more );
do {
      zmq_msg_t part;                       /* Create an empty ØMQ message to hold the message part */
      int rc = zmq_msg_init (&part);           assert (rc == 0 && "MSG_INIT failed" );
      rc = zmq_msg_recv (&part, socket, 0); /* Block until a message is available to be received from socket */
                                               assert (rc != -1 && "MSG_RECV failed" );
                                            /* Determine if more message parts are to follow */
      rc = zmq_getsockopt (socket, ZMQ_RCVMORE, &more, &more_size);
                                               assert (rc == 0 && "GETSOCKOPT failed" );
      zmq_msg_close (&part);
      } while (more);

鉴于RFC-23/ZMTP记录的属性,只有少数(导线级遥测编码)保证:

1)发送/传递所有邮件:

  • 原子地(所有帧都相同的无错误二进制文件,或者根本没有)
  • 最多一次(根据相关同行)
  • 有序
2)多部分消息会额外获得一个内部(带内)遥测状态“建议”

  • 位标记的状态
    {1:更多帧跟随| 0:没有更多帧}
  • 位标记的大小类型
    {0:8b直接八位字节| 1:64b-“网络端”-编码}
  • a大小-建议
    {0~255:直接大小| 0~2^63-1:64b-“网络端”-编码大小}

文档化的
zmq\u recv()
API在以下方面同样相当明确: 多部分信息

ØMQ消息由1个或多个消息部分组成。每个消息部分本身就是一个独立的
zmq\u msg\u t
。ØMQ确保消息的原子传递:对等方应接收消息的所有消息部分,或根本不接收除可用内存外,消息部分的总数不受限制。

处理多部分消息的应用程序在调用ZMQ_msg_recv()以确定是否还有其他部分要接收后,必须使用ZMQ_RCVMORE ZMQ_getsockopt(3)选项


无论第一次读取时看起来有多“丑陋”,内存中最糟糕的情况是在一个多部分消息框架中有大量的小消息

当然,由此产生的“清除-'em”的时间不是零,但紧凑高效的内部ZMTP遥测和低延迟流处理的好处是更重要的目标(并且已经实现)

如果有疑问,首先对最坏情况进行基准测试:

a) “生成”大约1E9多部分消息帧,传输零大小的有效载荷(无数据,但所有消息帧)

b) “设置”最简单的“拓扑”
推/拉

c) “选择您选择的”传输类
inproc:///ipc:///tipc:///124;……| vmci://}
)-最佳无堆栈
inproc:///code>(我将以此开始压力测试)

d) 秒表当zmq_POLLIN(zmq_POLLIN)
已确认存在任何可读取内容时,此类盲机械零快捷键会在
参考点-S:
之间“冲洗”,当多部分多部分消息的最后一条消息被盲人循环时,会出现
参考点-E:
-“冲洗器”-马戏团


结果解释: 在
[S]
[E]
之间花费的纳秒,确实可以作为最坏情况的证据,这段时间被“替罪羊”变成了一个明知是瞎的“冲洗者”“-循环马戏团。在现实世界的用例中,可能会有更多的理由花费更多的时间来做同样的事情

然而,公平的是,不要忘记,发送这种{明知如此大小|格式不良}-多帧BEAST责任是以超低延迟高延迟的方式处理此问题的任何运营风险的根本原因(几乎线性)-以可扩展性为重点的消息/信号框架


正是Zen of Zero的艺术让这一切得以实现。多亏了Pieter HINTJENS和他的团队,在Martin SÚSTRIK的领导下,我们都非常感谢他们能够进一步利用他们的遗产。

谢谢。所以这有点像过去我们称之为“链接列表”。如果我理解正确的话,那就数一数吧循环中的“more”标志确实是唯一的方法,但你是说我不应该担心时间,因此没有必要像在我的代码中那样设置任意限制(你是对的,我只应用了一个限制,因为我担心如果有太多的部分,它会持续很长时间).非常感谢您的详细回答-zmq库也是如此。
int recv_exhaust(void *socket,int *aremore)

// Receive the remainder of a multipart message and discard the contents.
// Use this to clean out a multi-part 'inbox' from a wrongly sent message.
// Returns 0 on success
// Returns -1 on zmq function failure
// Returns -2 on failure to exhaust even after 1000 parts.
{                                                          
 int len,rc,rcvmore,pdx;
 size_t rcvmore_size = sizeof(rcvmore);

 pdx=1;
 rcvmore=*aremore;

 while(rcvmore){
   len=zmq_recv(socket, mpartstr[0], BUFRCV, 0); if(len==-1) return len;
   rc=zmq_getsockopt(socket,ZMQ_RCVMORE,&rcvmore,&rcvmore_size); if(rc) return -1; 
   pdx++;
   if(pdx>1000) return -2;
 }

 return 0;
}
int    more;
size_t more_size = sizeof ( more );
do {
      zmq_msg_t part;                       /* Create an empty ØMQ message to hold the message part */
      int rc = zmq_msg_init (&part);           assert (rc == 0 && "MSG_INIT failed" );
      rc = zmq_msg_recv (&part, socket, 0); /* Block until a message is available to be received from socket */
                                               assert (rc != -1 && "MSG_RECV failed" );
                                            /* Determine if more message parts are to follow */
      rc = zmq_getsockopt (socket, ZMQ_RCVMORE, &more, &more_size);
                                               assert (rc == 0 && "GETSOCKOPT failed" );
      zmq_msg_close (&part);
      } while (more);