社区版 EMQX Broker 在发布消息时出现高耗时情况。

EMQX 版本:社区版 4.4.10

EMQX服务器版本:"CentOS 7.8 64bit

客户端版本:Java org.eclipse.paho.client.mqttv3 1.2.2

测试方式:使用两个 paho 客户端 A,B。A 收到消息时经服务器解析后由 B 重新发出。

测试压力:10W/分钟

现象:

  1. B客户端在paho的 MqttClient.publish(String topic, MqttMessage message) 方法中出现高耗时现象。耗时大概在 800ms 左右,出现频率为每1至2秒一次。
  2. 将 B 客户端对应 EmqxBroker 换为企业版 EMQX Enterprise 4.4.15 后现象消失

配置项:publish_limit,rate_limit配置项没有进行配置。active_n 为 100

客户端连接方式:tcp

看上去很不合理,有能复现的脚本么?
如果企业版本e4.4.15 没有问题,那么开源的4.4.15也应该没有问题的。关于连接的,2个代码是共用的。

可能是我的描述比较模糊,我是写服务器代码,然后 jmeter 发消息给服务器,服务器解析消息后【重新发送消息】,在【服务器重新发送消息】这部分时会周期性出现高耗时现象。基于这种测试方式我无法提供复现脚本。提问的目的主要想来问下这种情况有没有可能和 EMQX 有关,比如有不了解的配置、特性等,亦或者和使用的Paho Java Mqtt 客户端相关。

今天,我重新做了一次调查。换了一个服务器向 社区版 EMQX 发布消息后现象消失了。结合您的回答,和今天的现象来看高耗时的情况和EMQX 应该关联不大。正在重新检查发生高耗时的服务器代码,后续有结果或问题时再来讨论。

应该没有。

好的,保持联系。

!新情况,需要帮助!HELP :raised_hand:

情况概述

  1. 通过引入 Arthas 后定位到耗时主要出现在 服务器每次向 ”社区版 4.4.10 Emqx Broker“ SocketOutputStream.write 时发生。
  2. 之前描述中,我猜测是服务器部分代码的问题结论并不对。两个服务器比较时发现主要区别在于 【每次发送的Topic是否不同】。这也是我本次求助的主要方向。

测试方式与结果

  1. 使用 同一 Topic 向 ”社区版 4.4.10 Emqx Broker“ 发布消息,压力为 10W/分钟。发布高耗时情况并未发生。
  2. 使用 不同 Topic (保证每次发送时 Topic 唯一)向 ”社区版 4.4.10 Emqx Broker“ 发布消息,压力为 10W/分钟。发布耗时开始出现,且出现频率稳定,最高耗时在 800ms - 1000ms。
  3. 降低 Topic 唯一性(如:重复 Topic 占 10W/分钟 的一半),发布高耗时现象开始减少,最高耗时也降低为 200ms 左右。

提问与猜想

  1. 高耗时现象是否与 Topic 有关?根据我的测试结果来看,Topic 的唯一性是影响这个测试场景中的关键性因素,唯一性和发布耗时几乎成正比。
  2. 我使用的是 Java org.eclipse.paho.client.mqttv31.2.2客户端,我无法确认是 EMQX Broker 的问题,还是这个Java客户端的问题。下一步我会使用 Jmeter 进行发送并查看测试结果与耗时。

你用了通配符订阅么?
试着把这个配置打开,默认是关的(把前面的#去掉,然后重启再测试下)

## Enable trie path compaction.
## Enabling it significantly improves wildcard topic subscribe rate,
## if wildcard topics have unique prefixes like: 'sensor/{{id}}/+/',
## where ID is unique per subscriber.
##
## Topic match performance (when publishing) may degrade if messages
## are mostly published to topics with large number of levels.
##
## NOTE: This is a cluster-wide configuration.
## It rquires all nodes to be stopped before changing it.
##
## Value: Enum
##  - true: enable trie path compaction
##  - false: disable trie path compaction
# broker.perf.trie_compaction = true

更换配置后现象仍然出现。

broker.perf.trie_compaction = true

我这里测试的主要是发布场景,是发布mqtt消息的时候出现高耗时,并非订阅。同时服务器发布的 topic 没有任何客户端订阅。发布的消息 QOS 为 0。

当以每分钟十万的速率发布消息,且每个消息 Topic 不同时,发布耗时非常高。而当 Topic 相同时,同等压力下则不会出现这个现象。

!今日新发现

今天又进行了新的调查,有新的进展和问题,不知道对解决有没有帮助

@zhongwencool @heeejianbo

已知条件:

  1. EMQX 社区版 4.4.10 EmqxBroker
  2. EMQX服务器版本:CentOS 7.8 64bit

现象:

使用Java客户端向 EMQX Broker 发送消息(10W/min)时,单次发布出现高耗时现象。耗时可达 400ms - 1000ms。通过 arthas 追踪方法耗时,发现最终耗时在向 EmqxBroker 发送数据部分的代码(java.net.SocketOutputStream#socketWrite)。

调查结果:

今日新增:

  1. 使用 Paho Java 客户端和使用 Hive 客户端同样会出现高耗时情况
  2. 当部署至线上环境,即服务器A通过 TCP 内网 向 EmqxBroker 所在服务器发布消息时,会发生高耗时情况。而使用同一个版本的社区版EmqxBroker在本地测试(windows),通过本地 localhost TCP 发布消息时不会出现高耗时现象。【两个 EmqxBroker 同版本,同配置。仅运行环境不同】

既存结果:

  1. 社区版 4.4.10 有 此现象, 企业版 4.4.15 没有此现象
  2. 每次发布的 Topic 主题不同时,出现此现象。以 10W/min 发布同一主题,则不会出现高耗时。同时,若每分钟发送 10W 消息中,5W 消息同一主题,5W 消息主题不同,则现象也会对应减少。

看你说EMQX 同版本,同配置,都会有不一样的结果,那是不是有可能是网络或者系统没做调优?

@zhongwencool 调查发现我们的linux 服务器中没有

net.nf_conntrack_max

这个模块,这会对EMQX使用产生什么影响吗?

1 个赞

问了下GPT,应该没什么影响,tcp长链接都已经建立稳定了。

net.nf_conntrack_max这个内核参数是用于控制Linux系统中netfilter connection tracking表的最大大小。
netfilter是Linux内核中的一个框架,用于网络数据包过滤和处理。其中的connection tracking功能可以追踪通过系统的网络连接,以实现状态ful过滤。
为了追踪连接状态,netfilter会维护一个connection tracking表。这个表中记录了所有通过本机的网络连接及其状态。net.nf_conntrack_max就是这个表的最大条目数。
如果连接跟踪表溢出,新连接将会被丢弃。所以合理配置net.nf_conntrack_max参数,可以防止跟踪表溢出导致的连接问题。
net.nf_conntrack_max默认值往往不高,在高连接并发环境下可能会溢出。可以根据系统并发连接数进行调优,例如web服务器可以调大该值。
建议通过如下命令动态修改该参数:

sysctl -w net.nf_conntrack_max=65535

也可以修改/etc/sysctl.conf文件永久生效。

所以简单来说,net.nf_conntrack_max主要用来控制内核connection tracking表大小,避免高并发下表溢出引起的问题。

!今日新发现

今天尝试在另一台Linux机器上安装 EMQX 社区版 4.4.10 EmqxBroker 进行同样的测试。现象没有发生!

另:每条消息的 topic 为 54 byte, payload 为 369 byte。

今日新增:

  1. 两台 Linux 使用同版本EMQX,同版本同配置,一台出现该现象,一台没有出现该现象
  2. 两台 Linux 的配置项基本一致,下面是出现高耗时现象的Linux系统配置项对应优化项目的值
fs.file-max = 786387
fs.nr_open = 1048576
ulimit -n 65535
fs.file-max = 786387
DefaultLimitNOFILE=
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 1024
net.core.netdev_max_backlog = 1000
net.ipv4.ip_local_port_range = 32768    60999
net.core.rmem_default = 212992
net.core.wmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_max = 212992
net.core.optmem_max = 20480
net.ipv4.tcp_mem = 765819       1021092 1531638
net.ipv4.tcp_rmem = 4096        87380   6291456
net.ipv4.tcp_wmem = 4096        16384   4194304

nf_conntrack_max 相关模块无

net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_fin_timeout = 60

既存结果:

  1. 社区版 4.4.10 有 此现象, 企业版 4.4.15 没有此现象 比对后差异不在EMQX版本上

  2. :warning:每次发布的 Topic 主题不同时,出现此现象。以 10W/min 发布同一主题,则不会出现高耗时。同时,若每分钟发送 10W 消息中,5W 消息同一主题,5W 消息主题不同,则现象也会对应减少。

  3. 使用 Paho Java 客户端和使用 Hive 客户端同样会出现高时情况比对后差异不在使用的客户端

  4. 当部署至线上环境,即服务器A通过 TCP 内网 向 EmqxBroker 所在服务器发布消息时,会发生高耗时情况。而使用同一个版本的社区版EmqxBroker在本地测试(windows),通过本地 localhost TCP 发布消息时不会出现高耗时现象。【两个 EmqxBroker 同版本,同配置。仅运行环境不同】

1 个赞

@zhongwencool @heeejianbo 救救