跳到主要内容
英文版本为准

本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。

背压

订阅读取套接字时,最多领先处理器 read_ahead 条消息;超出就停止读取,等待一直传回对端的发送。

订阅的预读:消息沿左列向下走,通道满时的等待沿右列向上传回对端对端PUSH 或 PUB 发送内核的套接字缓冲区套接字任务读取一条消息通道深度为 read_ahead处理器或 workers(n) 工作分区处理器落后:通道已满任务等待,停止读取缓冲区填满,TCP 窗口关闭对端的发送等待空间在 PUB/SUB 上,PUB 等待最慢的匹配订阅者;不匹配任何过滤器的消息被丢弃
以文字阅读本图
  1. 对端 PUSH 或 PUB 发送 → 内核的 套接字缓冲区
  2. 内核的 套接字缓冲区 → 套接字任务 读取一条消息
  3. 套接字任务 读取一条消息 → 通道 深度为 read_ahead
  4. 通道 深度为 read_ahead → 处理器 或 workers(n) 工作分区
  5. 通道 深度为 read_ahead → 处理器落后: 通道已满
  6. 处理器落后: 通道已满 → 任务等待, 停止读取
  7. 任务等待, 停止读取 → 缓冲区填满, TCP 窗口关闭
  8. 缓冲区填满, TCP 窗口关闭 → 对端的发送 等待空间
  9. 在 PUB/SUB 上,PUB 等待最慢的匹配订阅者; 不匹配任何过滤器的消息被丢弃

订阅的任务从套接字上一次读一条消息,放进通道。通道容纳 read_ahead 条消息,默认 1000 条,即 libzmq 给套接字的接收高水位。这个设置由 Broker 携带,因此该 Broker 的每个订阅都预读这么远。

处理器落后时,通道被填满,任务等待空间。等待中的任务不读取任何东西,因此帧留在内核的缓冲区里,直到缓冲区填满。随后 TCP 让发送方停下,对端的发送一直等到处理器赶上来。慢的处理器会让发送方放慢,本进程的内存保持有界。

在 PUB/SUB 上,等待的发送方是 PUB 套接字。它依次写给每个匹配的订阅者,因此一个慢订阅者会拖住发给所有订阅者的消息。不匹配任何订阅者过滤器的消息仍然被丢弃,见队列一页的说明。

除非挂载点要求更多,处理器一次只取一条消息。workers(n) 并排运行 n 个处理器,空闲的工作者从通道取下一条消息。ZeroMQ 消息不带键,因此 workers(n, by_key) 没有可以哈希的东西,消息在各个工作分区之间轮转。批在达到挂载点指定的大小时结束,或者在第一条消息之后 20 毫秒结束。

对端读得慢时,发布也以同样的方式等待。队列发布在等待时可以取消,下一次发布会完成它的发送。广播发布、回复和请求不能这样取消,因此通过超时放弃它们。