一次redis集羣連接數佔滿問題的排查

現象

某系統的tomcat,收不到上游系統請求,日誌停止不滾動,進程還存活(俗稱的tomcat假死)。

分析排查

應用排查

1、登錄應用jstack -l pid > jstack.txt,查看堆棧信息,發現大量的連redis集羣的BLOCKED信息:

"http-nio-9080-exec-200" #287 daemon prio=5 os_prio=0 tid=0x00002aaad4716800 nid=0x47db waiting for monitor entry [0x000000005287e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at redis.clients.jedis.JedisClusterInfoCache.getSlotPool(JedisClusterInfoCache.java:151)
    - waiting to lock <0x0000000648ecf770> (a redis.clients.jedis.JedisClusterInfoCache)
    at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:54)
    at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:47)
    at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:32)
    at redis.clients.jedis.JedisCluster.get(JedisCluster.java:97)

2、登錄監控平臺,發現一個redis節點已經監控不到。在應用上telnet該節點,返回超過最大連接數。於是基本定位故障:某redis節點超過最大連接數,導致無法訪問。

 

分析問題

應用程序

  1. 應用程序在生成流水號時,強依賴redis,沒有做降級方案。
  2. 應用端jedispool設置了連接超時時間,但是過大,造成請求阻塞。
  3. 此redis集羣爲公用集羣,至少有60個子系統在使用,每個子系統都有設置了最大連接數,理論上,是不會超出10000的。


 

redis集羣排查

4、登錄redis-cli,list連接清單,發現了某應用集羣有大量的連接,並處於establish狀態,斷定來源IP爲問題應用,並且應用使用了redis的發佈訂閱功能:subscribe。

連接信息.png

5、登錄問題應用服務器,使用netstat查看未發現到redis服務器的連接。由此定位問題爲redis連接未及時釋放。


 

長連接問題排查

  1. 查看網絡拓撲爲應用->防火牆->redis。登錄防火牆,連接數依然爲0-1個,確認問題爲redis未及時回收連接。
  2. 查看操作系統tcp keepalive設置爲7200s(2小時),未生效,推測此配置被redis配置覆蓋。(在測試環境使用相同配置,進行tcpdump抓包測試,確認無誤。)
  3. 查看redis配置tcp_keepalive爲0,代表關閉tcp連接狀態檢查,與現象一致。
  4. 查看防火牆長連接配置爲30分鐘無流量主動斷開連接,與現象一致。

結論

  1. 應用與redis之間有jupiter防火牆,防火牆30分鐘無數據通信,會拆連接,拆的時候不會通知兩端回收連接。
  2. redis-server設置了keepalive=0,此配置覆蓋了操作系統的keepalive=7200s,導致redis-server不主動檢測連接狀態,所以不會主動回收連接。
  3. 客戶端應該是jvm有默認設置,或者走了操作系統的配置(待驗證),所以客戶端機器上可以正常回收連接。

解決方案

  1. redis設置tcp_keepalive=60s
  2. 應用程序jedispool設置連接檢測。

轉載:https://www.jianshu.com/p/e0fbcdd6eb73



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章