問題:
在項目中接入redis的訂閱消費功能,服務端發布消息,客戶端訂閱到消息后進行業務操作。結果發現在訂閱端會間歇性地出現超時問題
排查:
(1)開始以為就是超時,於是調整了redis的超時配置
原:connectTimeout=3 調整為:connectTimeout=10
但依然會報超時錯,並且一來redis操作的數據量並不大,二來其他的邏輯也存在同樣數據的操作,並沒有發生異常,所以判斷不是命令執行時間配置本身問題。
(2)通過觀察日志發現超時都是發生在訂閱邏輯之后,懷疑是訂閱的緩沖設置問題
於是查看當前緩沖設置
xx.xx.xx.xx:8080> config get client-output-buffer-limit 1) "client-output-buffer-limit" 2) "normal 0 0 0 slave 34359738368 8589934592 0 pubsub 33554432 8388608 60"
看出在訂閱消費模式下,當客戶端輸出緩沖達到32M或持續60s達到8M就會斷開客戶端連接。於是調大該參數
client-output-buffer-limit pubsub 64mb 16mb 120
依然還是報錯。
(3)經過長時間的日志觀察,發現只有在訂閱后進行redis操作,才會拋異常,所以進入redis官網查看發布/訂閱的文檔,發現以下兩處說法:
https://lettuce.io/core/release/reference/#pubsub.subscribing
https://lettuce.io/core/snapshot/reference/
https://zhuanlan.zhihu.com/p/44439782
https://lettuce.io/core/release/reference/#pubsub.subscribing
不要在發布訂閱的回調中發起阻塞的操作。
https://lettuce.io/core/snapshot/reference/
超時可能是因為阻塞操作打破了時間循環。
然后查看了代碼,發現確實在訂閱的回調中,發起了redis的阻塞命令。於是嘗試將訂閱動作和消息的處理邏輯解耦異步,在訂閱中只接受保存消息,然后用
另外的線程去處理消息。
最終異常沒有再出現。
排查過程記錄如上。