💬
前言:一个EMQX问题记录
最近遇到了EMQX的一个问题。在设置了客户端授权后,运行一段时间后,HTTP认证服务就会异常,客户端订阅或者发送消息失败,等待超时,会触发客户端重连,导致批量掉线。
出现问题的EMQX版本有5.0.13,5.0.26,环境有单机器,双机器组集群,连接数量不大,不到100个设备,新建MQTT请求数可能都没有1秒1个,负载很低。
notion image
而且出现问题时候,还不是所有客户端的所有请求都出问题,MQTT客户端连接是正常的,因为走的是【客户端认证】,与【客户端授权】的权限控制和资源池是分开的,这时候部分设备连接上EMQX后,订阅主题时,会出现等待服务端响应超时。
使用EMQX的【日志追踪】功能,在出问题时候对客户端进行日志抓出,会有类似以下的日志。
看起来像是后端接口的问题,但是使用postman请求或者用curl在EMQX部署的机器请求都是正常的,这就有点捉摸不定了。
为了进一步确认是EMQX的问题还是后端程序的问题,只能进一步排查了。
使用`netstat`命令查看EMQX上的TCP连接情况,会发现设置中的连接池数量就是EMQX向后端接口服务器建立的TCP连接数(用于发起HTTP请求)。
notion image
经过反复测试,发现应该是8个TCP长连接中,有一个连接EMQX这边不再发起HTTP请求导致的。为了进一步确认猜想,通过`tcpdump`命令抓取了EMQX的TCP报文,发现当客户端正常连接并订阅主题时,所有的授权请求都是由另外7条正常的TCP端口发出;重复多次复现该问题时,有问题的端口是一个HTTP授权请求都没有往授权服务端发送。
使用命令`/opt/emqx/bin/emqx eval 'observer_cli:start()’`打开监控工具,可以看到每个TCP连接的流量情况,有问题的连接数据量和发出、接受包都是不会增加了的,这个和tcp抓包的结果对应得上。
notion image
到这里,基本上就可以判断为EMQX内部连接管理的问题了,不过由于EMQX是Erlang语言写的,内部逻辑又比较复杂,实在没有梳理完内部逻辑确认问题。
出现问题时候,这个异常的TCP长连接,使用tcpkill工具也是没法断联的,这个和tcpkill工具的实现原理有关,断连前需要先识别流量,再发送 TCP RST(Reset)包,但是这个连接不知道因为什么问题异常了,一直保持着tcp连接,但是没有任何报文交互,也就没法通过外部工具断开连接了。
这时候关闭该HTTP授权,再开启,会触发断开原有的8个TCP连接,重新建立新的连接池,这时候问题就能暂时性解决,但是会在一个不确定的时间点又出现这问题,最近一个月内已经出现了两次,看起来没什么规律。
如果是因为当前新建连接太多,认证授权请求过多报的超时资源不可用,情况会是8个长连接都报异常,这时候可以通过尝试修改连接池配置,把默认值8改大一点,增加连接池长连接数量解决。
 
在官方论坛中,找到了一例和我遇到的问题很类似的案例,但这个案例问题是HTTP服务认证的问题。
notion image
notion image
GitHub上也有一个类似的问题:《Authentication and Authorization fail periodically》,不过这个问题看起来是因为这老哥在网关层的配置有问题,导致EMQX到网关保持着TCP长连接,而网关到后端有问题。
也因为看到这个问题,所以在我这出现问题时候,也检查了配置文件和环境,这里使用的是k8s作为后端服务,配置了授权service的node port,检查过了kube-proxy使用的iptables配置,以及EMQX上四元组和授权服务的pod上的四元组状态,看起来都是没有问题的。
notion image
 
 
 
 
解析Twitter的雪花算法及其变体【转载】大厂工作一年, 能攒多少钱?
Loading...