1. 程式人生 > 實用技巧 >【Azure Redis Cache】對StackExchange.Redis IOCP錯誤訊息的解讀

【Azure Redis Cache】對StackExchange.Redis IOCP錯誤訊息的解讀

問題描述

在使用StackExchange.Redis連線到Azure Redis服務時,時常出現StackExchange.Redis.RedisTimeoutException異常。

全部錯誤訊息為:

關鍵資訊為:

Timeout performing EXISTS (5000ms)

IOCP: (Busy=926, Free=1074,Min=200, Max=2000),

WORKER:(Busy=43,Free=32724,Min=200,Max=32767),

訊息解讀

執行EXISTS操作5000毫秒引起了RedisTimeoutException。 而關鍵資訊為在執行IOCP(I/O Completion Port, IOCP threads are used when asynchronous IO happens, such as when reading from the network.) Busy執行緒數達到926,遠遠超過Min值200。參考

Azure關於執行緒池增長的描述

一旦現有(Busy)執行緒數達到“Min”執行緒數,ThreadPool 便會將插入新執行緒的速率限制為每 500 毫秒一個執行緒。通常情況下,如果系統中出現需要 IOCP 執行緒的突發工作,則它會快速處理該工作。但是,如果突發工作多於配置的“Min”設定,則在處理某些工作時會出現一定的延遲,因為 ThreadPool 會等待發生以下兩種情況之一。

  • 一個現有執行緒釋放,以便處理工作。
  • 在 500 毫秒內沒有任何現有執行緒釋放,因此會建立一個新執行緒。

所以,如果 IOCP 執行緒受到限制,則 StackExchange.Redis 可以會超時。

解決辦法

考慮到此資訊,我們強烈建議客戶將 IOCP 和輔助角色執行緒的最小配置值設定為大於預設值我們無法提供有關此值應是多少的通用指導,因為一個應用程式的合適值對於另一個應用程式可能會太高或太低。此設定還可能會影響複雜應用程式其他部分的效能,因此每個客戶需要按照其特定需求來微調此設定。開始時設定為 200 或 300 會比較好,隨後可進行測試並根據需要進行調整。

建議使用global.asax.cs中的ThreadPool.SetMinThreads (...)法,以程式設計方式更改此設定。例如

private readonly int minThreads = 200;
void Application_Start(object
sender, EventArgs e) { // Code that runs on application startup AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ThreadPool.SetMinThreads(minThreads, minThreads); }

備註

此 方法指定的值是全域性設定,將影響整個 AppDomain。例如,如果已有 4 核計算機,並想要在執行時將minWorkerThreadsminIoThreads設定為 50(每個 CPU),可使用ThreadPool.SetMinThreads(200, 200)。

參考資料

Azure Cache for Redis 管理常見問題解答 : https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-management-faq#important-details-about-threadpool-growth