當您從 ASP.NET 應用程式呼叫 Web 服務時,效能問題
本文提供協助來解決從 Microsoft ASP.NET 應用程式呼叫 Web 服務時所發生的效能問題。
原始產品版本: ASP.NET
原始 KB 編號: 821268
徵兆
當您從 ASP.NET 應用程式呼叫 Web 服務時,可能會遇到爭用、效能不佳和死結。 用戶端可能會報告要求停止回應,或需要很長的時間才能執行。 如果懷疑死結,可能會回收背景工作進程。
當您呼叫 HttpWebRequest.GetResponse
方法時,可能會收到下列例外狀況錯誤訊息:
“System.InvalidOperationException:ThreadPool 對象中沒有足夠的可用線程來完成作業。
您也可以在瀏覽器中收到下列例外狀況錯誤訊息:
“HttpException (0x80004005):要求逾時。
注意
本文也適用於直接提出 HttpWebRequest
要求的應用程式。
原因
此問題可能會發生,因為 ASP.NET 會限制呼叫可用來執行要求的背景工作線程和完成埠線程數目。
一般而言,對 Web 服務的呼叫會使用一個背景工作線程來執行程式代碼,以傳送要求和一個完成埠線程,以從 Web 服務接收回呼。 不過,如果要求重新導向或需要驗證,呼叫可能會使用多達兩個背景工作線程和兩個完成埠線程。 因此,當多個 Web 服務呼叫同時發生時,您就可以耗盡 Managed ThreadPool
。
例如,假設 ThreadPool
限制為10個背景工作線程,而且所有10個背景工作線程目前正在執行正在等候回呼執行的程式碼。 回呼永遠無法執行,因為任何排入佇列的工作 ThreadPool
專案會遭到封鎖,直到線程變成可用為止。
另一個潛在的爭用來源是maxconnection
System.Net
命名空間用來限制連線數目的參數。 一般而言,此限制如預期般運作。 不過,如果許多應用程式嘗試同時對單一IP位址提出許多要求,線程可能必須等候可用的連線。
解決方法
若要解決這些問題,您可以在 Machine.config 檔案中微調下列參數,以最符合您的情況:
maxWorkerThreads
minWorkerThreads
maxIoThreads
minFreeThreads
minLocalRequestFreeThreads
maxconnection
executionTimeout
若要成功解決這些問題,請採取下列動作:
- 將可以同時執行的 ASP.NET 要求數目限制為每個 CPU 大約 12 個。
- 允許 Web 服務回呼在 中
ThreadPool
自由使用線程。 - 選取
maxconnections
參數的適當值。 根據您的選擇,以所使用的IP位址和AppDomains數目為基礎。
注意
將每個 CPU ASP.NET 要求數目限制為 12 的建議有點任意。 不過,此限制已證明適用於大多數應用程式。
MaxWorkerThreads 和 maxIoThreads
ASP.NET 使用下列兩個組態設定來限制使用的背景工作線程和完成線程數目上限:
<processModel maxWorkerThreads="20" maxIoThreads="20">
參數 maxWorkerThreads
和 maxIoThreads
參數會以隱含方式乘以CPU數目。 例如,如果您有兩個處理器,背景工作線程的最大數目是 2 * maxWorkerThreads
。
MinFreeThreads 和 minLocalRequestFreeThreads
ASP.NET 也包含下列組態設定,可決定必須有多少背景工作線程和完成埠線程才能啟動遠端要求或本機要求:
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
如果沒有足夠的線程可用,要求會排入佇列,直到有足夠的線程可供提出要求為止。 因此,ASP.NET 不會同時執行超過下列數目的要求:
(maxWorkerThreads
* CPU 數目) - minFreeThreads
注意
minFreeThreads
參數和 minLocalRequestFreeThreads
參數不會以隱含方式乘以CPU數目。
MinWorkerThreads
ASP.NET 也包含下列組態設定,可決定可立即提供給服務遠端要求的背景工作線程數目。
<processModel minWorkerThreads="1">
此設定所控制的線程可以比從 Common Language Runtime (CLR) 的預設線程微調功能建立的背景工作線程快得多。
此設定可讓 ASP.NET 服務要求,這些要求可能會因為後端伺服器上的速度變慢而突然填入 ASP.NET 要求佇列、來自用戶端的要求突然暴增,或導致佇列中要求數量突然增加的類似專案。
參數的 minWorkerThreads
預設值為 1。 我們建議您將 參數的值 minWorkerThreads
設定為下列值:
minWorkerThreads
=
maxWorkerThreads
/ 2
根據預設, minWorkerThreads
參數不存在於 Web.config 檔案或 Machine.config 檔案中。 此設定會以隱含方式乘以CPU數目。
Maxconnection
參數 maxconnection
會決定可對特定IP位址建立多少個連線。 參數如下所示:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>
如果應用程式的程式代碼以主機名稱而非IP位址參考應用程式,參數應該如下所示:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname" maxconnection="12">
</connectionManagement>
最後,如果應用程式裝載在 80 以外的埠上,參數必須在 URL 中包含非標準埠,如下所示:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname:8080" maxconnection="12">
</connectionManagement>
本文稍早討論之參數的設定全都在程式層級。 不過, maxconnection
參數設定會套用至 AppDomain 層級。 根據預設,由於此設定會套用至 AppDomain 層級,因此您最多可以從程式中每個 AppDomain 建立兩個特定 IP 位址的連線。
ExecutionTimeout
ASP.NET 使用下列組態設定來限制要求運行時間:
<httpRuntime executionTimeout="90"/>
您也可以使用 Server.ScriptTimeout
屬性來設定此限制。
注意
如果您增加參數的值executionTimeout
,您可能也必須修改processModel
responseDeadlockInterval
參數設定。
建議
本節中建議的設定可能無法適用於所有應用程式。 不過,下列其他資訊可協助您進行適當的調整。
如果您要從每個 ASPX 頁面對單一 IP 位址進行一個 Web 服務呼叫,Microsoft建議您使用下列組態設定:
- 將參數的值
maxWorkerThreads
和maxIoThreads
參數設定為 100。 - 將參數的值
maxconnection
設定為 12*N(其中 N 是您擁有的 CPU 數目)。 - 將參數的值
minFreeThreads
設定為 88*N ,並將minLocalRequestFreeThreads
參數設定為 76*N。 - 將的值
minWorkerThreads
設定為 50。 請記住,minWorkerThreads
預設不在組態檔中。 您必須新增它。
其中一些建議涉及伺服器 CPU 數目的簡單公式。 代表公式中 CPU 數目的變數為 N。
針對這些設定,如果您已啟用超線程,則必須使用邏輯 CPU 數目,而不是實體 CPU 數目。 例如,如果您有已啟用超線程的四個處理器伺服器,則公式中的 N 值會是 8,而不是 4。
注意
當您使用此組態時,可以同時執行每個CPU最多12個 ASP.NET 要求,因為100-88=12。 因此,至少有 88*N 個 背景工作線程和 88*N 個完成埠線程可供其他用途使用(例如 Web 服務回呼)。
例如,您有一部伺服器已啟用四個處理器和超線程。 根據這些公式,您會針對本文中所述的組態設定使用下列值。
<system.web>
<processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>
<httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/>
</system.web>
<system.net>
<connectionManagement>
<add address="[ProvideIPHere]" maxconnection="96"/>
</connectionManagement>
</system.net>
此外,當您使用此設定時,每個 AppDomain 的每個 IP 位址每個 CPU 都有 12 個連線可用。 因此,在下列案例中,當要求等候連線時,很少發生爭用,而且 ThreadPool
不會耗盡:
- Web 只裝載一個應用程式(AppDomain)。
- ASPX 頁面的每個要求都會提出一個 Web 服務要求。
- 所有要求都位於相同的IP位址。
不過,當您使用此組態時,牽涉到下列其中一個的案例可能會使用太多連線:
- 要求是多個IP位址。
- 要求會重新導向(302 狀態代碼)。
- 要求需要驗證。
- 要求是從多個 AppDomains 提出。
在這些案例中,最好針對 maxconnection
參數使用較低的值,以及參數和 參數的minLocalRequestFreeThreads
較高值minFreeThreads
。
其他相關資訊
如需詳細資訊,請參閱 改善 ASP.NET 效能。
如果您在 IIS 上遇到效能不佳和爭用 ASP.NET,請移至下列Microsoft部落格: