文介紹了如何通過異步方法消除使用 Microsoft ASP
NET 的 Web 服務調用的性能問題和線程池資源的消耗問題
情況從 ASPNET 頁面調用 Web 服務時的性能破壞 我們在本文中討論 Web 服務時
期望在各種情況下都可以享用 Web 服務
一個主要的情況是從中間層環境(如 ASP
NET Web 頁面)訪問 Web 服務
為 MapPoint
NET Web 服務的用戶提供支持的人員經常收到這樣的問題
即用戶在使用其 Web 服務時
對 MapPoint
NET 的調用可能需要相當長的時間
這本身並不是什麼問題
但某些其他因素可以使之成為比表面上要嚴重得多的大問題
HTTP 雙連接限制 HTTP 規范表明
一個 HTTP 客戶端與任一服務器最多可以同時建立兩個 TCP 連接
這可以防止單個浏覽器在浏覽某個頁面(例如
具有
個嵌入的縮略圖)時
由於連接請求過多而使服務器負載過重
此時
浏覽器將僅創建
個連接
然後通過這兩個管道開始發送
個 HTTP 請求
而不是創建
個 TCP 連接並通過每個連接來發送 HTTP 請求
對於中間層
此方法的問題在於
中間層可能會有
個同時請求連接的用戶
如果不得不為每個用戶進行一次 MapPoint
NET Web 服務調用
將會有
個用戶等待兩個管道中的一個空閒下來
線程池限制 ASP
NET 處理傳入的請求的方式是通過一個稱為進程線程池的一組線程為其提供服務
正常情況下
請求傳入後
池中某個空閒的線程將為其提供服務
這裡的問題在於
進程線程池不會創建無數個線程來處理大量的請求
具有最大線程數限制是一件好事
因為如果我們無限地創建線程
計算機上的全部資源將只能用來管理這些線程了
通過限制所能創建的線程數
我們可以把線程管理的系統開銷保持在一個可控的水平
如果某個請求傳入時線程池中的所有線程都被占用
則該請求將排隊等候
在忙線程完成任務後
空閒出來的線程才能處理新請求
此方法實際上比切換到某個新線程更有效
因為不需要在請求之間進行線程切換
但存在的問題是
如果線程的使用效率不高(尤其是在非常忙的 Web 服務器上)
則等候的請求隊列會變得很大
考慮一下從 ASP
NET 頁面進行 Web 服務調用的情況
如果進行同步調用
則正在運行的線程將被阻塞
直到 Web 服務調用完成為止
在調用期間
線程無法進行任何其他活動
它無法處理其他請求
只能等待
如果某個單處理器計算機上具有默認的工作線程數
則只需
個同時進行的請求即可用完全部線程
以後的請求必須排隊等候
該問題不僅限於 Web 服務 不僅調用 Web 服務的用戶會遇到從 Web 頁面進行調用時的擁堵且耗時較長的問題
進行任意數量的較長的調用都會遇到同樣的問題
例如
SQL Server? 請求
長文件的讀取或寫入
各種 Web 請求或訪問某個並發資源(其中鎖定會造成嚴重的延遲)
實際上
有許多使用 Web 服務的情況
其服務調用比較迅速
並不是什麼問題
但您或許會理解
如果您想通過代理服務器調用 MapPoint
NET Web 服務
所使用的連接具有一定的延遲
同時相應的服務可能又要花費一些時間來處理請求
則您可能在各處位置都看到延遲的情況
並且如果站點很忙
便可能出現問題
改善問題 該問題的某些方面可以通過對環境進行某些配置設置來改善
我們看一下可用於改善該問題的某些配置設置
maxconnections
連接到 Web 資源的默認雙連接限制可以通過一個名為 connectionManagement 的配置元素來控制
connectionManagement 設置允許您添加要讓其采用非默認連接限制的站點的名稱
可以將以下內容添加到典型的 nfig 文件中
將您連接的所有服務器的連接限制默認值增加到
<configuration>
<>
<connectionManagement>
<add address=
*
maxconnection=
/>
</connectionManagement>
</>
<system
web>
應當注意的是
對本地計算機的連接數量從來都沒有限制
因此
如果是連接到本地主機
則此設置無效
maxWorkerThreads 和 minFreeThreads
如果收到 HTTP
錯誤(
服務暫時過載
)
則表明線程池中的線程已全部占用
並且請求隊列也已超出最大值(appRequestQueueLimit 的默認設置為
)
對於 IIS
安裝
可以簡單地增加線程池的大小
而對於 IIS
安裝(與 IIS
不兼容)
這些設置將無效
maxWorkerThreads 和 maxIoThreads 分別控制工作線程數以及處理新提交的 ASP
NET 請求的線程數
這些設置需要在您的 nfig 中進行配置
它們將影響您計算機上運行的所有 Web 應用程序
maxWorkerThreads 是 nfig 中的 processModel 元素的一部分
並且您在查看後會發現
該設置的默認值為每個處理器
個線程
minFreeThreads 設置可以在 nfig 中進行配置
或者在您的應用程序的 nfig 文件中的 httpRuntime 元素下進行配置
該設置的作用是
當空閒的線程數低於所設置的限制時
將禁止使用線程池中的線程來處理傳入的 HTTP 請求
如果您需要某個進程線程池線程完成掛起的請求
這會很有用
如果所有的線程都被用來處理傳入的 HTTP 請求
並且這些請求在等待另一個線程完成其處理
那麼就會進入死鎖狀態
例如
如果您正在從 ASP
NET 應用程序進行對某個 Web 服務的異步 Web 服務調用
並且在等待回調函數完成該請求
就會出現這種情況
因為回調必須在進程線程池中的空閒線程上進行
如果查看一下您的 nfig
將會注意到 minFreeThreads 設置的默認值為
如果工作線程池的限制為
則該默認值還可以滿足需要
但是
如果線程池的大小增加到
該默認值就太小了
應當注意的是
如果您的 ASP
NET 應用程序對本地計算機進行 Web 服務調用
則線程池限制的問題將被激化
例如
我為此專欄創建的測試應用程序調用與 ASPX 頁面同處一台計算機上的 Web 服務
因而
對於阻塞的調用
一個線程被同時用於 ASPX 頁面和 ASMX Web 服務請求
這有效地使 Web 服務器處理的同時請求數增加了一倍
在同時進行兩個 Web 服務請求(使用異步 Web 服務調用)的情況下
我們最終使同時進行的請求數增加了兩倍
為避免在回調本地計算機時出現此類問題
您應當考慮您的應用程序的體系結構
使其簡單地直接從 ASPX 代碼來執行 Web 方法中的代碼
Windows XP 限制 我們必須要注意
如果您在一個 Windows? XP 計算機上進行某項測試
則所面臨的另一個限制是 XP Web 服務器對所允許的同時連接數的人為限制
因為 Windows XP 不是服務器平台
其同時連接數被限制為
這對於開發環境中的測試通常沒問題
但是如果試圖進行任何復雜的測試
該限制問題就會比較嚴重
本地計算機的連接不受此限制影響
真正的解決方案異步請求處理 調整配置設置是一種改善問題的方法
而在實際設計 Web 應用程序時通過某種方式徹底解決問題則是另一回事
等待阻塞的調用完成的線程永遠也不會有更好的調整余地
因此
解決的辦法是完全避免阻塞問題
異步處理請求就是一個適當的解決方案
這表現在兩個方面
進行異步 Web 服務調用
以及在 ASP
NET Web 應用程序中異步處理請求
異步 Web 服務調用 在以前的專欄中
我寫了有關異步調用 Web 服務的問題
能夠使線程不用等待 Web 服務調用完成是創建釋放線程以便處理更多請求的異步頁面處理模型的關鍵部分
此外
異步調用 Web 服務也比較簡單
請考慮以下 ASPX 頁面的 Visual Basic
NET 代碼
錯用同步 Web 服務調用所造成的性能極差的
頁面!
Public Class SyncPage
Inherits System
Web
UI
Page
Protected WithEvents Label
As System
Web
UI
WebControls
Label
Protected WithEvents Label
As System
Web
UI
WebControls
Label
Private Sub Page_Load(ByVal sender As System
Object
_
ByVal e As System
EventArgs) Handles MyBase
Load
調用 Web 服務
Dim proxy As New localhost
Service
Label
Text = proxy
Method
(
)
Label
Text = proxy
Method
(
)
End Sub
End Class
此代碼非常易懂
頁面加載時將創建一個 Web 服務代理實例
然後用該實例兩次調用一個名為 Method
的 Web 方法
Method
只返回包含傳遞給該方法的輸入參數的字符串
為了向該系統添加一定程度的延遲
Method
在返回字符串之前還休眠了
秒鐘
從調用返回到 Method
的字符串被放在 ASPX 頁面上的兩個標簽的文本中
該頁面提供的性能極差
並且像一塊海綿一樣從進程線程池中吸取線程
由於在 Method
Web 方法中有
秒鐘的延遲
對該頁面的一個調用至少要
秒鐘才能完成
以下代碼片段顯示了一個類似 Web 頁面的代碼
只不過現在進行的是異步 Web 服務調用
Public Class AsyncPage
Inherits System
Web
UI
Page
Protected WithEvents Label
As System
Web
UI
WebControls
Label
Protected WithEvents Label
As System
Web
UI
WebControls
Label
Private Sub Page_Load(ByVal sender As System
Object
_
ByVal e As System
EventArgs) Handles MyBase
Load
調用 Web 服務
Dim proxy As New localhost
Service
Dim res As IAsyncResult
= proxy
BeginMethod
(
Nothing
Noth
From:http://tw.wingwit.com/Article/program/net/201311/13406.html