1、錯誤日志
關鍵日志:Caused by: java.net.SocketTimeoutException: connect timed out
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.GeneratedConstructorAccessor122.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:342)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2188)
at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2037)
... 21 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:211)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:301)
... 23 common frames omitted
2、分析
1、檢查配置的db host是否有誤,檢查結果:host正確
2、在容器內ping數據庫的host是否能ping通,檢查結果:能ping通
3、檢查calico網絡組件日志是否正常,檢查結果:日志正常,要是calico有故障,影響的是所有的項目
4、聯系網絡同事檢查網絡是否有問題或有對該機房網絡是否有進行過調整,反回結果是沒有變更操作
5、聯系dba同事查看數據庫是否有慢查詢和數據庫連接數是否高,反回結果都是正常
6、檢查pod使用內存情況,檢查結果:正常
7、咨詢成都側有沒有遇到類似的問題,反回結果檢查下數據庫服務器和node節點服務器的時間戳參數
8、受成都側的提醒,加上聯想到之前北京db側有個自動化系統在職場訪問時好時壞,於是找dba查看故障業務所用數據庫的系統參數,發現開啟了net.ipv4.tcp_tw_recycle這個參數,而且通過netstat -s|grep rejected查看,被拒絕的包一直在增加,於是建議dba修改net.ipv4.tcp_tw_recycle為0,表示關閉該參數
3、定位問題
改完參數net.ipv4.tcp_tw_recycle為0后,大概過了10分鍾,在db服務器上通過命令查看netstat -s|grep rejected這個值沒有再增加,業務側在改完參數后,也沒有反饋系統無法使用,日志方面,也沒有再出現無法連接數據庫的報錯日志,通過在網上查詢資料定位到問題原因:由於pod內連接數據庫經過了一次NAT轉換,客戶端TCP請求到達數據庫,修改目的地址(IP+端口號)后便轉發給數據庫服務器,而客戶端時間戳數據沒有變化。對於數據庫來說,請求的源地址是node節點IP,所以從數據庫的角度看,原本不同客戶端的請求經過NAT的轉發,就可能會被認為是同一個連接,加之不同客戶端的時間可能不一致,所以就會出現時間戳錯亂的現象,於是后面的數據包就被丟棄了,具體的表現通常是是客戶端明明發送的SYN,但服務端就是不響應ACK,還可以通過下面命令來確認數據包不斷被丟棄的現象:netstat -s|grep rejected
4、問題解決
在故障業務所在數據庫上設置net.ipv4.tcp_tw_recycle為0,其實這個參數默認是關閉的,開啟net.ipv4.tcp_tw_recycle的目的,就是希望能夠加快TIME_WAIT狀態的回收,但其實linux官方是不建議開啟這個參數,可以通過在服務上通過man tcp查看:
tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4) Enable fast recycling of TIME_WAIT sockets. Enabling this option is not recommended since this causes problems when working with NAT (Network Address Translation).
並且該參數在內核4.10內核后徹底沒有了用武之地,並且在4.12內核中被移除,生產k8s node節點都有升級過內核至4.18,通過命令查看會發現已找不到該值
[root@ser10-13 ~]# sysctl net.ipv4.tcp_tw_recycle
sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: 沒有那個文件或目錄
5、思考
通過抓包發現為什么pod注冊dubbo是pod的IP,連接數據庫和redis以及mq就通過了NAT轉換成node節點的IP?
6、參考鏈接
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4396e46187ca5070219b81773c4e65088dac50cc #net.ipv4.tcp_tw_recycle參數被移除的文章
https://www.iyunw.cn/archives/xie-lin-lin-jiao-xun-sheng-cheng-huan-jing-bu-yao-luan-xiu-gai-net-ipv4-tcp-tw-recycle/ #血淋淋教訓,生產環境不要亂修改net.ipv4.tcp_tw_recycle
https://blog.csdn.net/zhuyiquan/article/details/68925707 #tcp_tw_recycle參數引發的系統問題
https://blog.csdn.net/wireless_tech/article/details/6405755 #【經驗總結】tcp_tw_recycle參數引發的故障