生产环境MQTT消息响应缓慢的故障排查

  生产环境的充电桩项目一直运行平稳,用户在H5页面上操作,扫描充电桩,而后可以支付,进入对应的界面可以控制该充电桩的放电、停电。

  具体的控制流程为,用户在页面通过HTTPS协议与服务器进行交互,服务器接收到请求后,组装参数,发送消息到mqtt服务器(RabbitMQ),而后充电桩的Mqtt客户端即可收到该条消息。充电桩对页面的消息反馈刚好是一个相反的过程。

  该项目上线后,消息的发送到硬件响应平均时间基本在2s左右(视当地的4G网络信号)。但一天下午,小区的客户反馈,整个过程变得特别慢,下单后放电成功,但页面迟迟不会跳转到放电展示的界面,而且点击页面停电按钮,也不会生效。

  首先,查看服务器上的H5模块的日志,发现但凡是传入该模块Mqtt消息的,服务器上都已经成功处理,没有延迟的情况。所以怀疑是当地充电桩硬件的信号问题(此前不久曾发生某小区大规模4G无信号、弱信号的情况)。为了保险,在办公室里调试并安装了一套硬件设备,模拟线上的情况,发现下发,响应很及时,没有出现延迟的情况。所以当即让现场人员检查,但现场人员经过十几分钟测试,反应4G信号没有问题。

  没办法,只能再次多次的在办公室进行问题复现,现场也有人员进行配合测试。结果确实发现有消息漏传到服务器的情况。即,上传成功的消息,服务器都处理成功,没有上传成功的,服务器没有处理,页面只能处于等待状态并进入后续的等待处理流程。此时,为了验证充电桩是否真的漏传消息,还是因为什么别的原因服务器没有处理该条消息,开启了一个Mqtt客户端,并设置好环境,连上生产环境的服务器后,调到对应的topic并开启消费端,结果发现,充电桩的所有消息上传是正常的,但服务器这边确实没有接收到。此时,想到会不会是有多个程序,设置了相同的clientid,同时在消费生产环境的消息。经过各个服务器(允许连入生产环境IP)的排查,发现确实有一个消费端,与生产环境的MQTT消息消费模块分享了所有消息。将该消费端的进程kill掉,生产环境立即恢复正常。

  其实,这个问题之前已多次发生,但每次都会以不尽相同的场景出现,而且由于相同终端ID消费消息策略的不同,还可能出现有些时候测试响应及时,有些响应却很慢的情况,对排查问题造成了干扰。比如起初调试硬件mqtt消息时,由于硬件工程师对该协议细节不甚清楚,结果将所有的硬件烧录了完全相同的代码,即clientid也相同。这样,当两个以上硬件同时在线时,就相当于两个clientId相同的消费端同时开启,这样原本发送给某一个消费端的消息就可能会被另一个接收,目标消费端不会有反应,而服务器在发现目标消费端没有反应后,会启动重发机制,最终目标消费端接收到消息后,会给人造成一种通信延迟的假象。一开始只有一个硬件调试时,一切正常,但当硬件开启了几个之后,就表现出网络不畅的现象,一度怀疑是办公区域的网络问题。其实是几个终端共同消费了同一通道的所有消息,导致漏收。虽然有重发机制保障整个流程能够完整执行,但是整个过程会显得特别卡顿,整个执行周期相当漫长。之前在使用kafka的过程中,同样也遇到过类似的问题。

  不过在大数据量处理过程中,该特性却是一个可以用来分散流量的解决方案。比如海量终端生产数据上传到消息队列中,开一个消费端,可能根本无法承受这么大的数据流量,无法及时的处理,所以此时必须在不同服务器,开启多个终端,使用相同的终端ID,才能分享并及时处理该批消息。

  记录一下,涉及消息队列的问题排查中,这个问题点值得关注。

上一篇:关系型数据库中好友关系的设计


下一篇:面向对象