問題:
Cannot send, channel has already failed: tcp://ip:61616
Javax.jms.JMSException: Cannot send, channel has already failed: tcp://ip:61616
應用連不上mq
解決方案:
一,分析思路:
1.現(xiàn)象:通過netstat 查看與61616相關的連接狀況,發(fā)現(xiàn)130多個CLOSE_WAIT
2.是什么原因造成這么多的CLOSE_WAIT?
2.1 主要原因是某種情況下應用關閉了socket連接,但是mq忙于讀或者寫,沒有關閉連接.
2.2 代碼需要判斷socket,一旦讀到0,斷開連接,read返回負,檢查一下errno,如果不是AGAIN,就斷開連接。
3.造成CLOSE_WAIT之后服務為啥連不上mq呢?
linux分配給一個用戶的文件句柄是有限的,CLOSE_WAIT狀態(tài)一直被保持,意味著對應數(shù)目的通道就一直被占著,一旦達到句柄數(shù)上線,新的請求就無法被處理了,應用程序可能會返回大量的Too many openfiles異常.
4.什么是CLOSE_WAIT?
4.1 mq為被連接端,java服務為主動方,在被動關閉情況下,mq已經(jīng)接收到FIN,但是還沒有發(fā)送自己的FIN的時刻,連接處于CLOSE_WAIT狀態(tài);
二,解決辦法:
1.重啟mq
2,linux下設置如下三個參數(shù):
/proc/sys/net/ipv4/tcp_keepalive_time當keepalive起用的時候,TCP發(fā)送keepalive消息的頻度。缺省是2小時。
/proc/sys/net/ipv4/tcp_keepalive_intvl當探測沒有確認時,重新發(fā)送探測的頻度。缺省是75秒。
/proc/sys/net/ipv4/tcp_keepalive_probes在認定連接失效之前,發(fā)送多少個TCP的keepalive探測包。缺省值是9。這個值乘以tcp_keepalive_intvl之后決定了,一個連接發(fā)送了keepalive之后可以有多少時間沒有回應。
三.了解擴展
1.客戶端先發(fā)送FIN,進入FIN_WAIT1狀態(tài)
服務端收到FIN,發(fā)送ACK,進入CLOSE_WAIT狀態(tài),客戶端收到這個ACK,進入FIN_WAIT2狀態(tài)
服務端發(fā)送FIN,進入LAST_ACK狀態(tài)
客戶端收到FIN,發(fā)送ACK,進入TIME_WAIT狀態(tài),服務端收到ACK,進入CLOSE狀態(tài)
客戶端TIME_WAIT持續(xù)2倍MSL時長,在linux體系中大概是60s,轉(zhuǎn)換成CLOSE狀態(tài)
2.服務端使用的短鏈接,每次客戶端請求后,服務端都會主動發(fā)送FIN關閉連接.最后進入到time_wait狀態(tài).對于訪問量大的web server,會存在大量的TIME_WAIT狀態(tài).讓服務器能夠快速回收和重用那些TIME_WAIT的資源,可修改內(nèi)核參數(shù).
修改/etc/sysctl.conf如下:
#對于一個新建連接,內(nèi)核要發(fā)送多少個 SYN 連接請求才決定放棄,不應該大于255,默認值是5,對應于180秒左右時間
net.ipv4.tcp_syn_retries=2
#表示當keepalive起用的時候,TCP發(fā)送keepalive消息的頻度。缺省是2小時,改為300秒
net.ipv4.tcp_keepalive_time=1200
net.ipv4.tcp_orphan_retries=3
#表示如果套接字由本端要求關閉,這個參數(shù)決定了它保持在FIN-WAIT-2狀態(tài)的時間
net.ipv4.tcp_fin_timeout=30
#表示SYN隊列的長度,默認為1024,加大隊列長度為8192,可以容納更多等待連接的網(wǎng)絡連接數(shù)。
net.ipv4.tcp_max_syn_backlog = 4096
#表示開啟SYN Cookies。當出現(xiàn)SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN***,默認為0,表示關閉
net.ipv4.tcp_syncookies = 1
#表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認為0,表示關閉
net.ipv4.tcp_tw_reuse = 1
#表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉
net.ipv4.tcp_tw_recycle = 1
##減少超時前的探測次數(shù)
net.ipv4.tcp_keepalive_probes=5
##優(yōu)化網(wǎng)絡設備接收隊列
net.core.netdev_max_backlog=3000
修改完之后執(zhí)行/sbin/sysctl -p讓參數(shù)生效。