你是否正遇到網絡或 CPU 的瓶頸?
驗證客戶端和托管redis-server的服務器上支持的最大帶寬。如果有請求被帶寬限制,則它們需要更長時間才能完成,從而可能導致超時。
同樣,驗證您沒有在客戶端或服務器框上獲得CPU限制,這將導致請求等待CPU時間,從而超時。
有沒有命令需要在 redis 服務器上處理很長時間?
可能有一些命令需要很長時間才能在redis服務器上處理,導致請求超時。
長時間運行的命令的很少例子有 mget有大量的鍵,鍵*或寫得不好的lua腳本。
可以運行通過 SlowLog 命令查看是否有請求花費比預期更長的時間。
在這里 可以找到關于命令的更多細節。
在向Redis發出的幾個小請求之前是否有大的請求超時?
錯誤消息中的參數“qs”告訴您有多少從客戶端發送到服務器,但尚未處理響應的請求。
對于某些類型的加載,您可能會看到此值不斷增長,因為 StackExchange.Redis 使用單個TCP連接,并且一次只能讀取一個響應。
即使第一個操作超時,它也不會停止 向服務器發送/從服務器發送 數據,其他請求也會被阻塞,直到該操作完成。 從而,導致超時。
一個解決方案是通過確保redis-server緩存對于您的工作負載足夠大并將大值分割為更小的塊來最小化超時的可能性。
另一個可能的解決方案是在客戶端中使用 ConnectionMultiplexer 對象池,并在發送新請求時選擇“最小化加載”ConnectionMultiplexer。 這樣可能會防止單個超時導致其他請求也超時。
在超時異常中,是否有很多 busyio 或 busyworker 線程?
讓我們先了解一下 ThreadPool 增長的一些細節:
CLR ThreadPool有兩種類型的線程 - “工作線程”和“I/O 完成端口”(也稱為 IOCP)線程。
- 工作線程用于處理
Task.Run(...)
或ThreadPool.QueueUserWorkItem(...)
方法時。當工作需要在后臺線程上發生時,這些線程也被CLR中的各種組件使用。 - 當異步IO發生時(例如從網絡讀取),使用IOCP線程。
線程池根據需要提供新的工作線程或I / O完成線程(無任何調節),直到達到每種類型線程的“最小”設置。 默認情況下,最小線程數設置為系統上的處理器數。
一旦現有(繁忙)線程的數量達到“最小”線程數,ThreadPool將調節每500毫秒向一個線程注入新線程的速率。 這意味著如果你的系統需要一個IOCP線程的工作,它會很快處理這個工作。 但是,如果工作突發超過配置的“最小”設置,那么在處理一些工作時會有一些延遲,因為ThreadPool會等待兩個事情之一發生:
1. 現有線程可以自由處理工作
2. 連續 500ms 沒有現有線程空閑,因此創建一個新線程。
基本上,這意味著當忙線程數大于最小線程時,在應用程序處理網絡流量之前,可能需要付出500毫秒的延遲。
此外,重要的是要注意,當現有線程保持空閑超過15秒(基于我記得),它將被清理,這個增長和收縮的循環可以重復。
如果我們看一個來自 StackExchange.Redis(build 1.0.450或更高版本)的示例錯誤消息,您將看到它現在會打印 ThreadPool 統計信息(請參閱下面的IOCP和WORKER詳細信息)。
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個最小線程。 在這種情況下,客戶端可能會看到兩個500毫秒的延遲,因為6> 4。
請注意,如果 IOCP 或 WORKER 線程的增長受到限制,StackExchange.Redis 可以命中超時。
建議:
鑒于上述信息,建議將 IOCP 和 WORKER 線程的最小配置值設置為大于默認值的值。 我們不能給出一個大小適合所有指導這個值應該是什么,因為一個應用程序的正確價值將太高/低為另一個應用程序。
此設置也會影響復雜應用程序的其他部分的性能,因此您需要根據您的特定需求調整此設置。
一個好的起點是200或300,然后根據需要進行測試和調整。
如何配置這個設置:
- 在 ASP.NET 中,使用 machine.config 中
<processModel>
配置元素下的“minIoThreads”配置設置。
如果您在Azure WebSites內部運行,則此設置不會通過配置選項顯示。 您應該能夠從global.asax.cs 中的 Application_Start 方法以編程方式設置(請參見下文)。
重要說明: 此配置元素中指定的值是為每個核 設置。例如,如果你有一個4核的機器,并希望你的 minIthreads 設置為200在運行時,你應該使用
<processModel minIoThreads =“50”/>
。
- 在 ASP.NET 之外,使用 ThreadPool.SetMinThreads(...)API。
查看原文
More
作者水平有限,若有疏漏或錯誤還望提醒,十分感謝。
您可以在這里 提出問題 。