redis connect timeout問題排查
問題表現:週期性出現connect timeout: 具體如下:
redis.clients.jedis.exceptions.JedisConnectionException
java.net.SocketException
java.net.SocketTimeoutException: connect timed out
問題定位:redis 引數tcp-backlog預設設定過小(還有別的可能會造成上面的問題,但是我這次是因為這個)
這個場景下,如果我們到伺服器上看看 listen情況,watch "netstat -s | grep listen",會看到“xxx times the listen queue of a socket overflowed”,並且這個xxx在不斷增加,這個xxx就是我們沒有對網路請求正常處理的次數
問題分析:
首先說下TCP中backlog
Linux核心為每個TCP伺服器程式維護兩條backlog佇列,一條是TCP層的未連線佇列,一條是應用層的已連線佇列,分別對應net.ipv4.tcp_max_syn_backlog和net.core.somaxconn兩個核心引數。
一個客戶端連線在完成TCP 3次握手之前首先進入到未連線佇列,完成握手之後正式建立連線,進入已連線佇列,交付給應用程式處理。應用程式呼叫accept()函式從已連線佇列取出連線進行處理。應用層在呼叫listen()函式時指定的backlog是已連線佇列大小,如果大於somaxconn將被設為somaxconn。
解釋:針對redis server來說已經完成三次握手的tcp連線進入accept 佇列,然後等待redis server去從accept 佇列中取出來和redis server建立連線,然後accept 佇列就會減少一個值。這裡說的accept 佇列是由net.core.somaxconn和redis引數tcp-backlog的最小值來控制!
核心問題:如果應用層不呼叫accept()函式處理一個連線,或者處理不及時的話,將會導致已連線佇列堆滿。已連線佇列已滿的話會導致未連線佇列在處理完3次握手之後無法進入已連線佇列,最終也導致未連線佇列堆滿,在伺服器看到處於未連線佇列中的連線狀態為SYN_RECV。 新進來的客戶端連線將會一直處於SYN_SENT狀態等待伺服器的ACK應答,最終導致連線超時。
檢視佇列大小:
檢視未連線佇列值:
[root@t1-26-89 redis-3.0.7]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
262144
檢視已連線佇列值:
[root@t1-26-89 redis-3.0.7]# cat /proc/sys/net/core/somaxconn
32768
修改佇列大小:可以直接改寫這兩個檔案的值。要永久修改這兩個核心引數的話可以寫到/etc/sysctl.conf:
改完後執行sysctl -p 讓修改立即生效。
vim /etc/sysctl.conf
net.ipv4.tcp_max_sync_backlog=1024
net.core.somaxconn = 2048
sysctl -p
再次解釋下tcp三次握手:
我們看到Send-Q的值為100, 即是我們配置的tcp-backlog值. 為了搞清楚這個值的意思, 瞭解了下tcp的三次握手進行中的一些queue的知識. 參考下圖我們可以看到在server接收到sny的時候會進入到一個syn queue佇列, 當server端最終收到ack時轉換到accept queue佇列. 然後透過ss或者netstat就可以看到listen狀態下的連線, 其Send-Q就是這個accept queue佇列的最大值. 只有server端執行了accept後才會從這個佇列中移除這個連線. 這個值的大小是受somaxconn影響的, 因為是取的它們兩者的最小值, 所以如果要調大的話必需修改核心的somaxconn值.
關於redis 的引數tcp-backlog:
預設值 511, 如果tcp-backlog大於/proc/sys/net/core/somaxconn值,則截斷為/proc/sys/net/core/somaxconn值
tcp-backlog:511
此引數確定了TCP連線中已完成佇列(完成三次握手之後)的長度, 當然此值必須不超過Linux系統定義的/proc/sys/net/core/somaxconn值(預設引數值是128),tcp-backlog引數預設是511。當系統併發量大並且客戶端速度緩慢的時候,可以將這二個引數一起參考設定。
建議修改為 2048
修改somaxconn
該核心引數預設值一般是128,對於負載很大的服務程式來說大大的不夠。一般會將它修改為2048或者更大。
echo 2048 > /proc/sys/net/core/somaxconn 但是這樣系統重啟後儲存不了
在/etc/sysctl.conf中新增如下
net.core.somaxconn = 2048
然後在終端中執行
sysctl -p
總結:redis的每個引數都值得研究,做出合適的調整,針對redis server來說已經完成三次握手的tcp連線進入accept 佇列,然後等待redis server去從accept 佇列中取出來和redis server建立連線,然後accept 佇列就會減少一個值。這裡說的accept 佇列是由net.core.somaxconn和redis引數tcp-backlog的最小值來控制!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29654823/viewspace-2790380/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis阻塞問題排查方向Redis
- Redis效能問題排查解決手冊(七)Redis
- INBOUND_CONNECT_TIMEOUT與SQLNET.INBOUND_CONNECT_TIMEOUT小結SQL
- java問題排查Java
- JVM 問題排查JVM
- 框架問題排查框架
- Redis 大key(bigkey)問題的排查與解決方案Redis
- SDK與問題排查
- connect by 的排序問題排序
- 線上FullGC問題排查實踐——手把手教你排查線上問題GC
- 線上問題排查:記一次 Redis Cluster Pipeline 導致的死鎖問題Redis
- 聊聊jdk httpclient的connect timeout異常JDKHTTPclient
- 線上問題排查例項分析|關於 Redis 記憶體洩漏Redis記憶體
- 線上問題排查例項分析|關於Redis記憶體洩漏Redis記憶體
- Java服務.問題排查.問題復現Java
- 異常問題排查之旅
- Spark學習——問題排查Spark
- 利用greys排查java問題Java
- JVM問題排查步驟JVM
- 資料問題排查思路
- Linux排查JVM問題LinuxJVM
- Mysql show processlist 排查問題MySql
- 【問題處理】IPC Send timeout detected
- 關於Corba呼叫的Timeout 問題ORB
- JAVA死鎖排查-效能測試問題排查思路Java
- [開源精品] .NET Redis Client 又多了一個選擇,還在被 StackExchange.Redis Timeout 問題困擾嗎?Redisclient
- [求助] start with connect by 奇怪的問題
- 微信支付返回-1,問題排查
- 運維排查問題常用sql運維SQL
- 伺服器問題 排查思路伺服器
- 日常問題排查-呼叫超時
- kubernetesgraceperiod失效問題排查
- 排查 “Detected Tx Unit Hang”問題
- 線上效能問題初步排查方法
- TNS問題排查 The listener supports no services
- MySQL:connect_timeout引數簡單記錄MySql
- adb connect 出現timeout的處理方式
- 【問題追查】mc叢集寫入恍惚問題排查