环境信息
- EMQX 版本:EMQ开源版4.3.11
- 操作系统及版本:CentOS 7.4.1708
- 其他:helm部署,认证方式:mongo认证,mongo使用的是Shareded
问题描述
测试场景:在连的20W设备全部断连之后再重连。
断连之后的设备不会改变认证信息,按照道理来说应该能够与EMQ建立连接,但是日志中大批量地报EMQ连接Mongo超时以及认证失败。
断连的时候,Mongo的连接数以及CPU的使用率都正常,相关EMQ连接Mongo的配置会放在下面(主要列举Mongo的参数)
麻烦帮忙解决一下 连接Mongo超时,以及为何认证失败的问题。
配置文件及日志
Mongo的配置文件:
EMQX_AUTH__MONGO__POOL: '100'
EMQX_AUTH__MONGO__QUERY_TIMEOUT: 5s
EMQX_AUTH__MONGO__TYPE: sharded
EMQX_AUTH__SUPER_QUERY: 'off'
如果可以的话,可以提供一些优化EMQ查询Mongo的参数
1 加大连接池大小,在配置中有参数 pool_size, 如果是使用dashboard创建的,可以直接找到连接池大小这个配置项的。
2 看下mongo的服务性能怎么样,是否已经达到极限
3 如果不是测极限状态,可以限制一下链接速率,让mongo的消耗小一些
我们一般不测试全断开然后一起上线20W个设备这种场景
1 EMQX服务还是很稳定的,除非网络故障导致的设备断开会有大量重连,EMQX本身基本不宕机
2 20W设备,需要考虑上负载均衡了,前置的负载均衡服务可以找稳定的服务商买,还是很靠谱的
你说的是auth.mongo.pool这个参数吗?
不用写的过大,符合你的硬件规格即可。可以使用cpu核心数*2起步,测一下能不能满足你的要求
我不太明白的是为什么一机一密的username和password都没变,为什么重连就会有那么多认证失败的报错
高并发场景都会遇到的问题。跟username pwd变化没有关系的。还有就是你是怎么处理的断开呢?拔网线还是杀掉所有的设备,还是重启了EMQX?
我们的负载均衡是阿里的,我直接把mqtt的端口的监听关掉测试断连
而且重连的时候,发现EMQ一直在踢出设备,导致EMQ这边一直在处理设备的连接。因此长时间EMQ没办法恢复正常的服务
踢出是说有kick_out take_over 的日志吗?看下是不是设备自动重连的周期太短了导致的?
踢设备我是从设备的日志里分析出来,稳定的情况下,设备端日志没有频繁连接,断连的现象。但是重连,高QPS的情况下,设备日志里就会有频繁连接,断连的现象,导致EMQ这边服务一直在处理设备的上下线,最终EMQ就宕机了,连接数也恢复不到断连前的状态。
负载均衡监控连接数:
断连之后就会出现连接数不稳定,一会接上来又断开,周而复始
重连的时间设备端是有退避算法的,这个周期应该会慢慢变长。
1 可以先关闭 mongo 认证,看下EMQX本身是否有性能瓶颈
2 如果没有认证的情况下,瓶颈消除了,可以开启认证,然后在压测过程中使用这个命令
./bin/emqx remote_console
进入EMQX的控制台,文件路径要替换成你的部署路径
在EMQX控制台中输入
observer_cli:start().
进入EMQX的htop,观察一下占用内存最高的进程是哪个(如果是连接的压力测试,可能内存最高的是cm channel manager进程,属于正常现象), 再看下MsgQueue的堆积情况,是哪类服务在堆积消息。
这个是其中一个pod的htop情况
你说的cm是emqx_cm吧,但是这个底下broker的消息堆积量好像有点大0.0
设备有订阅操作吗? cm的堆积没关系的,broker好像在做订阅关系
EMQ这边配了代理订阅,但是不太清楚设备端会不会主动再去订阅,我先咨询一下
订阅是创建集群路由表,可能有很多性能损耗在了订阅上,可以看下订阅了多少topic,还有topic的层级不要过多,10层以下没啥问题,只要不是几百层的那种就行。
代理订阅其实也是走的设备自己订阅的业务流程,只是不用设备主动发一个订阅报文,代理订阅可以看作给设备添加了一个脚本,登录之后自动完成了一些订阅工作,实际的操作还是设备进程自己做的。
压测过程可以监控一下EMQX主机的性能,内存和CPU到了多少。
资讯了设备,确实设备上线的时候会主动去订阅报文,这部分应该损耗了较大的性能
把设备主动订阅的操作去掉,看看性能如何
一般来说,一台设备只会订阅4个topic,层级也不高,就4层
可以考虑把 EMQX的htop,这个监控命令放到文档里,哈哈哈
是故意不放的,因为这个控制台里的权限太高了,基本上所有的操作都可以,并且是没有异常捕获的,不推荐非专业维护人员使用。
切忌
q().
会让EMQX直接杀掉,ctrl + c退出即可