• 正确主动关闭连接


    如果服务端没有考虑到各种异常场景,很难稳定运行,本章以生产环境 MQTT服务无法提供接入服务为例,详细介绍MQTT服务和Netty在异常场景下的保护机制。

    问题:

    生产环境的MQTT服务运行一段时间之后,发现新的端侧设备无法接入,连接超时。分析MQTT服务端日志,没有明显的异常,但是内存占用较高, 查看连接数,发现有数十万个TCP连接处于ESTABLISHED状态,实际的MQTT连接数应该在1万个左右,显然这么多连接肯定存在问题。由于MQTT服务端的内存是按照2万个左右连接数规模配置的,因此当连接数达到数十万个的规模之后,导致了服务端大量SocketChannel积压、内存暴涨、高频率GC和较长的STW时间,对端侧设备的接入造成了很大影响,部分设备MQTT握手超时,无法接入。
    通过抓包分析发现,一些端侧设备并没有按照MQTT协议规范进行处理,包括:
    (1) 客户端发起CONNECT连接,SSL握手成功之后没有按照协议规范继续处理,例如发送PING命令
    (2) 客户端发起TCP连接,不做SSL握手,也不做后续处理,导致TCP连接被挂起
    由于服务端是严格按照MQTT 规范实现的,上述端侧设备不按规范接入,实际上消息调度不到MQTT应用协议层。MQTT服务端依赖Keep Alive机制进行超时检测,当一段时间接收不到客户端的心跳和业务消息时,就会触发心跳超时,关闭连接 针对上述两种接入场景 ,由于MQTT的连接流程没有完成,MQTT协议栈不认为这个是合法的MQTT连接,因此心跳保护机制无法对上述TCP连接进行检测。客户端和服务端都没有主动关闭这个连接,导致TCP连接一直保持

    MQTT接入过程:

    服务端需要做一些可靠性保护,以防止客户端非正常操作带来的无效连接暴增:

    (1)端侧设备的 TCP连接接入后,启动一个链路检测定时器加入NioEventLoop。
    (2)链路检测定时器一旦触发,就主动关闭TCP连接。
    (3)TCP连接完成MQTT协议层的CONNECT之后,删除之前创建的链路检测定时器。
  • 相关阅读:
    为什么程序开发中不推荐使用全局变量?
    Spring系列文章:Spring中的设计模式
    yolo改进替换VanillaNet backbone
    微信推出自研NLP大规模语言模型WeLM,现已开放API推动应用落地
    day09_数组进阶
    微信小程序开发-01-入门
    十几张高清世界地图
    Word处理控件Aspose.Words功能演示:使用 C# 在 Word 文档中创建条形码
    aosp集成证书和过root检测
    51.【结构体初始化的两种方法】
  • 原文地址:https://blog.csdn.net/qq_34448345/article/details/127440049