關於StackExchange.Redis的超時問題


場景

某個讀取應用信息列表的接口突然出現大量異常和超時,該接口主要讀取出Redis緩存中的全部應用列表,再進行業務過濾返回結果數據,然后看異常信息如下所示。

部分關鍵異常日志如下

IOCP: (Busy=0,Free=1000,Min=100,Max=1000), 
WORKER: (Busy=82,Free=32685,Min=100,Max=32767), 
Local-CPU: unavailable 

看日志信息的意思是CPU資源不可用,導致了Redis請求的阻塞,這里記錄一下出現原因和解決方式:

1. 在超時異常中,是否有很多 busyio 或 busyworker 線程?

CLR ThreadPool有兩種類型的線程 - “工作線程”和“I/O 完成端口”(也稱為 IOCP)線程。

  • 工作線程用於處理 Task.Run(...) 或 ThreadPool.QueueUserWorkItem(...) 方法時。當工作需要在后台線程上發生時,這些線程也被CLR中的各種組件使用。
  • 當異步IO發生時(例如從網絡讀取),使用IOCP線程。
    線程池根據需要提供新的工作線程或I / O完成線程(無任何調節),直到達到每種類型線程的“最小”設置。
  • 默認情況下,最小線程數設置為系統上的處理器數。

一旦現有(繁忙)線程的數量達到“最小”線程數,ThreadPool將調節每500毫秒向一個線程注入新線程的速率。 如果你的系統需要一個IOCP線程的工作,線程池馬上可以分配出線程工作。 但是如果工作突發超過配置的“最小”設置,那么在處理一些工作時會有一些延遲,因為ThreadPool會等待兩個事情之一發生:

  • 現有線程可以自由處理工作
  • 連續 500ms 沒有現有線程空閑,因此創建一個新線程。

基本上,這意味着當忙線程數大於最小線程時,在應用程序處理網絡流量之前,可能需要付出500毫秒的延遲。 此外,重要的是要注意,當現有線程保持空閑超過15秒(記憶中是的),它將被清理,這個增長和收縮的循環可以重復。

StackExchange.Redis打印錯誤消息如下:

System.TimeoutException: Timeout performing GET MyKey, inst: 2, mgr: Inactive, queue: 6, qu: 0, qs: 6, qc: 0, wr: 0, wq: 0, in: 0, ar: 0,
IOCP: (Busy=6,Free=994,Min=4,Max=1000), 
WORKER: (Busy=3,Free=997,Min=4,Max=1000)

在上面的錯誤消息中,IOCP信息行中,忙碌線程數量為6,設置的最少線程數量為4,這時候忙碌IO線程數量大於最少線程數量,這意味着會有兩個請求的耗時會大於500ms。

IOCP 或 WORKER 線程的增長受到限制,StackExchange.Redis 可能會超時。所以當請求數量突然上漲時,服務中並沒有足夠的線程資源可以使用,線程池會有很大的線程初始化壓力,一定的堆積之后,StackExchange.Redis便會超時。

所以為了更好的性能考慮,不建議將線程池的工作線程和IO線程最小數量設置為默認值,具體的值可以根據服務的請求壓力合理設置,一般200左右是比較合理的值,具體關於線程池設置的詳細信息在我另一篇博客中有寫到:

關於使用ThreadPool.SetMinThreads方法提升API服務響應性能的總結

2. 有沒有命令需要在 redis 服務器上處理很長時間?

可能有一些命令需要很長時間才能在redis服務器上處理,導致請求超時。 長時間運行的命令的很少例子有 mget有大量的鍵,鍵*或寫得不好的lua腳本。 可以運行通過 SlowLog 命令查看是否有請求花費比預期更長的時間。

3. 在向Redis發出的幾個小請求之前是否有大的請求超時?

錯誤消息中的參數“qs”告訴您有多少從客戶端發送到服務器,但尚未處理響應的請求。 對於某些類型的加載,您可能會看到此值不斷增長,因為 StackExchange.Redis 使用單個TCP連接,並且一次只能讀取一個響應。 即使第一個操作超時,它也不會停止 向服務器發送/從服務器發送 數據,其他請求也會被阻塞,直到該操作完成。 從而,導致超時。 一個解決方案是通過確保redis-server緩存對於您的工作負載足夠大並將大值分割為更小的塊來最小化超時的可能性。

另一個解決方案是在客戶端中使用 ConnectionMultiplexer 對象池,並在發送新請求時選擇“最小化加載”ConnectionMultiplexer。 這樣可能會防止單個超時導致其他請求也超時。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM