1.一次 Netty 代码不健壮导致的源码大量 CLOSE_WAIT 连接原因分析
2.QT+ModbusTCP 基于QTcpSocket纯手搓modbustcp协议
3.åµå
¥å¼linuxè¦å¦åªäº
一次 Netty 代码不健壮导致的大量 CLOSE_WAIT 连接原因分析
我们线上存在一个 Dubbo 服务,遇到大量 CLOSE_WAIT 状态的源码连接,始终无法消失,源码因此进行了原因分析。源码 CLOSE_WAIT 状态出现在被动关闭方,源码收到对端 FIN 包后回复 ACK,源码区块链官方源码但未发送 FIN 包之前。源码问题在于服务没有回复 FIN,源码原因可能是源码收到了 FIN 包却未发送响应,通过抓包验证了这一情况。源码 问题核心在于为什么没有回复 FIN。源码Dubbo 服务底层使用 Netty,源码php时时彩获取源码作为普通的源码 TCP 服务端,关键在于 FIN 包的源码回复。 分析显示,源码如果服务没有发送 FIN 包,可能原因有: 1. 半连接队列或全连接队列积压,通过 ss 命令查看全连接队列大小和等待 accept 的连接个数。 2. LISTEN 状态的 socket,Recv-Q 表示等待用户进程 accept 的连接个数,Send-Q 表示全连接队列最大容纳的连接数。 非 LISTEN 状态的 socket,Recv-Q 表示 receive queue 字节大小,三阴线公式源码Send-Q 表示 send queue 字节大小。 通过 ss 命令确认 Recv-Q 为 0,全连接队列无积压。 嫌疑指向 Netty 没有注册事件,导致收到 FIN 包后无动于衷。 进一步发现,凌晨 1 点业务实例加载大量数据导致堆内存占满,持续进行 fullgc。Netty 线程出现 OOM 异常。在 org.jboss.netty.channel.socket.nio.NioServerBoss#process 方法中,Netty 调用 accept 取走连接,人事局网站源码第 行尝试注册事件时抛出 java.lang.OutOfMemoryError 异常。 因此,Netty 处理不健壮,try-catch 包裹了 accept 连接和注册事件逻辑,在 OOM 异常处理时,未能成功注册事件或关闭连接,导致连接存在但不被监听处理。 推荐相关视频学习:LinuxC++零拷贝的实现 用户态协议栈 ntytcp
支撑互联网的基石 TCP/IP,5个方面全面解析
TCP/IP协议栈深度解析丨实现单机百万连接丨优化三次握手、四次挥手
LinuxC++后台服务器开发架构师免费学习地址
为模拟问题复现,可使用字节码注入或直接重构 Netty 源码。网赚推荐导航站源码本地拥有 Netty 源码,采用重构方法更快。重新构建项目后,使用 nc 模拟健康检查握手并断开连接,CLOSE_WAIT 状态连接持续存在直至 Netty 进程退出。再次 nc 断开连接,新增 CLOSE_WAIT 状态。由于服务持续进行健康检查,导致 OOM 期间 CLOSE_WAIT 状态不断增加。 问题核心:Netty 代码不够健壮,尝试捕获异常时,未能正确处理连接注册事件或关闭连接,导致连接存在且未被监听。 修改方式:在 catch 处理 throwable 时关闭连接即可,最新版本的 Netty 代码这部分逻辑已优化,将 accept 和注册事件拆分。有兴趣的读者可以尝试。 学习 TCP、网络编程是解决类似问题的关键。QT+ModbusTCP 基于QTcpSocket纯手搓modbustcp协议
一、编写缘由
1.发现问题
近期项目需将modbus RTU转换为TCP形式,于是对原有modbus通讯线程进行重构。起初使用Qt自带的QModbusTcpClient类,顺利重构线程并读取数据,但在发送写数据请求时,TCP连接会断开。经过多次尝试,排除从站问题,即便直接连接modbusslave也存在同样问题。
2.查找问题
为解决问题,自行编写了一个tcp server,抓取QModbusTcpClient写数据的报文,与modbuspoll上的对比,发现QT中的报文比modbuspoll上的多出一部分,推测是协议错误。
3.解决策略
既然QModbusTcpClient的协议存在问题,决定不使用它。因此,直接利用QTcpSocket手动编写一个ModbusTcp类。
二、代码编写
1.协议解析
通过对比modbuspoll上的通信日志和网络上的modbustcp协议分析文章,研究出协议的标准格式。
2.封装函数
共封装了4个函数,分别是写单个线圈、写多个线圈、写单个保持寄存器、写多个保持寄存器。具体实现如下:
四个函数中,除了写多个线圈存在问题外,其他均已验证,可正确写入。
最后,将TCP作为一个子线程,线程初始化函数如下:
三、源码下载
模块下载
四、最后的最后再吐槽一下QModbusTcpClient真的很糟糕,根本无法使用。另外,网上的QtModbusTCP资源都无法使用,只有和我一样纯手搓才能解决问题。
åµå ¥å¼linuxè¦å¦åªäº
æ¨å¥½ï¼å ³äºè¯¥é®é¢ï¼è§£çå¦ä¸ï¼
åµå ¥å¼linuxè¦å¦ä»ä¹ï¼
1.Linux åºç¡
ããå®è£ Linuxæä½ç³»ç» Linuxæä»¶ç³»ç» Linux常ç¨å½ä»¤ Linuxå¯å¨è¿ç¨è¯¦è§£ çæLinuxæå¡è½å¤ç¬ç«å®è£ Linuxæä½ç³»ç» è½å¤çç»ä½¿ç¨Linuxç³»ç»çåºæ¬å½ä»¤ 认è¯Linuxç³»ç»ç常ç¨æå¡å®è£ Linuxæä½ç³»ç» Linuxåºæ¬å½ä»¤å®è·µ 设置Linuxç¯å¢åé å®å¶Linuxçæå¡ Shell ç¼ç¨åºç¡ä½¿ç¨viç¼è¾æ件 使ç¨Emacsç¼è¾æ件 使ç¨å ¶ä»ç¼è¾å¨
ãã2.Linux ä¸ç C ç¼ç¨åºç¡
ããlinux Cè¯è¨ç¯å¢æ¦è¿° Gcc使ç¨æ¹æ³ Gdbè°è¯ææ¯ Autoconf Automake Makefile 代ç ä¼å çæLinuxç³»ç»ä¸çå¼åç¯å¢ çæGccç¼è¯å¨ çæMakefileè§åç¼åHello,Worldç¨åº ä½¿ç¨ makeå½ä»¤ç¼è¯ç¨åº ç¼å带æä¸ä¸ªå¾ªç¯çç¨åº è°è¯ä¸ä¸ªæé®é¢çç¨åº
ãã3.Shell ç¼ç¨åºç¡
ããShell ç®ä» 认è¯åå°ç¨åºBashç¼ç¨çæLinuxç³»ç»ä¸çç¼è¾ç¯å¢ çæLinuxä¸çåç§Shell çç»è¿è¡shellç¼ç¨çæviåºæ¬æä½ çæEmacsçåºæ¬æä½ æ¯è¾ä¸åshellçåºå« ç¼åä¸ä¸ªæµè¯æå¡å¨æ¯å¦è¿éçshellèæ¬ç¨åº ç¼åä¸ä¸ªæ¥çè¿ç¨æ¯å¦åå¨çshellèæ¬ç¨åº ç¼åä¸ä¸ªå¸¦æ循ç¯è¯å¥çshellèæ¬ç¨åº
ãã4.åµå ¥å¼ç³»ç»å¼ååºç¡
ããåµå ¥å¼ç³»ç»æ¦è¿° 交åç¼è¯ é ç½®TFTPæå¡ é ç½®NFSæå¡ ä¸è½½Bootloaderåå æ ¸ åµå ¥å¼Linuxåºç¨è½¯ä»¶å¼åæµç¨çæåµå ¥å¼ç³»ç»æ¦å¿µä»¥åå¼åæµç¨ 建ç«åµå ¥å¼ç³»ç»å¼åç¯å¢å¶ä½cross_gccå·¥å ·é¾ ç¼è¯å¹¶ä¸è½½U-boot ç¼è¯å¹¶ä¸è½½Linuxå æ ¸ ç¼è¯å¹¶ä¸è½½Linuxåºç¨ç¨åº
ãã5.åµå ¥å¼ç³»ç»ç§»æ¤
ããLinuxå æ ¸ä»£ç å¹³å°ç¸å ³ä»£ç åæ ARMå¹³å°ä»ç» å¹³å°ç§»æ¤çå ³é®ææ¯ ç§»æ¤Linuxå æ ¸å° ARMå¹³å° äºè§£ç§»æ¤çæ¦å¿µ è½å¤ç§»æ¤Linuxå æ ¸ç§»æ¤Linux2.6å æ ¸å° ARM9å¼åæ¿
ãã6.åµå ¥å¼Linuxä¸ä¸²å£éä¿¡
ãã串è¡I/Oçåºæ¬æ¦å¿µ åµå ¥å¼Linuxåºç¨è½¯ä»¶å¼åæµç¨ Linuxç³»ç»çæ件åè®¾å¤ ä¸æ件ç¸å ³çç³»ç»è°ç¨ é ç½®è¶ çº§ç»ç«¯åMiniCOM è½å¤çæè¿è¡ä¸²å£éä¿¡ çææ件I/O ç¼å串å£éä¿¡ç¨åº ç¼åå¤ä¸²å£éä¿¡ç¨åº
ãã7.åµå ¥å¼ç³»ç»ä¸å¤è¿ç¨ç¨åºè®¾è®¡
ããLinuxç³»ç»è¿ç¨æ¦è¿° åµå ¥å¼ç³»ç»çè¿ç¨ç¹ç¹ è¿ç¨æä½ å®æ¤è¿ç¨ ç¸å ³çç³»ç»è°ç¨äºè§£Linuxç³»ç»ä¸è¿ç¨çæ¦å¿µ è½å¤ç¼åå¤è¿ç¨ç¨åºç¼åå¤è¿ç¨ç¨åº ç¼åä¸ä¸ªå®æ¤è¿ç¨ç¨åº sleepç³»ç»è°ç¨ä»»å¡ç®¡çãåæ¥ä¸éä¿¡ Linuxä»»å¡æ¦è¿°ä»»å¡è°åº¦ 管é ä¿¡å· å ±äº«å å ä»»å¡ç®¡ç API äºè§£Linuxç³»ç»ä»»å¡ç®¡çæºå¶ çæè¿ç¨é´éä¿¡çå ç§æ¹å¼ çæåµå ¥å¼Linuxä¸çä»»å¡é´åæ¥ä¸éä¿¡ç¼åä¸ä¸ªç®åç管éç¨åºå®ç°æä»¶ä¼ è¾ ç¼åä¸ä¸ªä½¿ç¨å ±äº«å åçç¨åº
ãã8.åµå ¥å¼ç³»ç»ä¸å¤çº¿ç¨ç¨åºè®¾è®¡
ãã线ç¨çåºç¡ç¥è¯ å¤çº¿ç¨ç¼ç¨æ¹æ³ 线ç¨åºç¨ä¸çåæ¥é®é¢äºè§£çº¿ç¨çæ¦å¿µ è½å¤ç¼åç®åçå¤çº¿ç¨ç¨åºç¼åä¸ä¸ªå¤çº¿ç¨ç¨åº
ãã9.åµå ¥å¼ Linux ç½ç»ç¼ç¨
ããç½ç»åºç¡ç¥è¯ åµå ¥å¼Linuxä¸TCP/IPç½ç»ç»æ socket ç¼ç¨ å¸¸ç¨ APIå½æ° åæPingå½ä»¤çå®ç° åºæ¬UDPå¥æ¥å£ç¼ç¨ 许å¯è¯ç®¡ç PPPåè®® GPRS äºè§£åµå ¥å¼Linuxç½ç»ä½ç³»ç»æ è½å¤è¿è¡åµå ¥å¼Linuxç¯å¢ä¸çsocket ç¼ç¨ çæUDPåè®®ãPPPåè®® çæGPRS 使ç¨socket ç¼å代çæå¡å¨ 使ç¨socket ç¼åè·¯ç±å¨ ç¼å许å¯è¯æå¡å¨ æåºTCPåUDPçä¼ç¼ºç¹ ç¼åä¸ä¸ªwebæå¡å¨ ç¼åä¸ä¸ªè¿è¡å¨ ARMå¹³å°çç½ç»ææ¾å¨
ãã.Linux å符设å¤é©±å¨ç¨åº
ãã设å¤é©±å¨ç¨åºåºç¡ç¥è¯ Linuxç³»ç»ç模å å符设å¤é©±å¨åæ fs_operationç»æ å 载驱å¨ç¨åºäºè§£è®¾å¤é©±å¨ç¨åºçæ¦å¿µ äºè§£Linuxå符设å¤é©±å¨ç¨åºç»æ è½å¤ç¼åå符设å¤é©±å¨ç¨åºç¼åSkullé©±å¨ ç¼åé®çé©±å¨ ç¼åI/Oé©±å¨ åæä¸ä¸ªçé¨ç驱å¨ç¨åº 对æ¯Linux2.6å æ ¸ä¸2.4å æ ¸ä¸å符设å¤é©±å¨çä¸åLinux å设å¤é©±å¨ç¨åºå设å¤é©±å¨ç¨åºå·¥ä½åç å ¸åçå设å¤é©±å¨ç¨åºåæ å设å¤ç读å请æ±éåäºè§£Linuxå设å¤é©±å¨ç¨åºç»æ è½å¤ç¼åç®åçå设å¤é©±å¨ç¨åºæ¯è¾å符设å¤ä¸å设å¤çå¼å ç¼åMMCå¡é©±å¨ç¨åº åæä¸ä¸ªæä»¶ç³»ç» å¯¹æ¯Linux2.6å æ ¸ä¸2.4å æ ¸ä¸å设å¤é©±å¨çä¸å
ãã.GUI ç¨åºå¼å
ããGUIåºç¡ åµå ¥å¼ç³»ç»GUIç±»å ç¼è¯QT è¿è¡QTå¼åçæåµå ¥å¼ç³»ç»å¸¸ç¨çGUI è½å¤è¿è¡QTç¼ç¨ä½¿ç¨QTç¼åâHelloï¼Worldâç¨åº è°è¯ä¸ä¸ªå å ¥ä¿¡å·/槽çå®ä¾ éè¿éè½½QWidget ç±»æ¹æ³å¤çäºä»¶
ãã.æ件系ç»
ããèææ件系ç»æ件系ç»çå»ºç« ramfså åæä»¶ç³»ç» procæä»¶ç³»ç» devfs æä»¶ç³»ç» MTDææ¯ç®ä» MTDå设å¤åå§å MTDå设å¤ç读åæä½äºè§£Linuxç³»ç»çæ件系ç»äºè§£åµå ¥å¼Linuxçæ件系ç»äºè§£MTDææ¯ è½å¤ç¼åç®åçæ件系ç»ä¸º ARM9å¼åæ¿æ·»å MTDæ¯æ移æ¤JFFS2æä»¶ç³»ç» éè¿procæ件系ç»ä¿®æ¹æä½ç³»ç»åæ° åæromfs æ件系ç»æºä»£ç å建ä¸ä¸ªcramfs æ件系ç»
ââå¦æ帮å©ï¼è¯·é纳ä¸ä¸ã