作者:Dflying Chen ( http://dflying.cnblog.som/ )
對於Atlas程序,在某些情況下,我們需要在短時間內調用大量的Web Service,例如某個列表中用戶快速的點擊刪除。這時網路頻寬,穩定程度等等往往會造成較長時間的延遲。如果可以將這些呼叫包裝成單一的請求,那麼使用者只需忍受一次網路延遲,即可得到處理的結果,也間接的提高了效率。似乎這並不是一個很容易實現的功能,但幸運的是,Atlas中內建了對批量調用Web Service的支持,您所需要的只是在程式中簡單設定一下。
Atlas中每個Web Service的呼叫請求都有三個優先權:0:高,1:中,2:低,預設值為中。
在呼叫的時候您可以透過priority參數(請參考:在ASP.NET Atlas中呼叫Web Service-處理錯誤,逾時以及回應使用者的取消操作)指定本次呼叫的優先權。對於高優先級的調用,Atlas並未應用批次調用,每次都會立即發送該請求;對於中和低優先級的調用,Atlas會將一定時間(請參考下面WebRequestManager的介紹)內的調用包裝成一個單獨的請求一起發送,或當待呼叫的請求達到指定數目(請參考下面WebRequestManager的介紹)時一起發送。其中如果待呼叫的請求太多,那麼會從中挑選優先順序的請求先呼叫。
啟用Atlas內建的批次呼叫Web Service支持,您首先需要在web.config中註冊伺服器端處理批次呼叫的handler(預設的Atlas Web Site Template已經啟用了這個handler):
<httpHandlers>
<add verb="*" path="atlasbatchcall.axd" type="Microsoft.Web.Services.MultiRequestHandler" validate="false"/>
</httpHandlers>
然後在頁面的Atlas XML腳本中加入WebRequestManager的顯示聲明並設定該頁面允許對Web Service的批次呼叫: <script type="text/xml-script">
<page xmlns:script=" http://schemas.microsoft.com/xml-script/2005 ">
<components>
<webRequestManager batchSize="5" enableBatching="true" batchDelay="3000" />
</components>
</page>
</script>
這裡您需要注意的是WebRequestManager的以下三個屬性:
enableBatching:設定該頁面是否允許批次調用,預設值為false。這裡我們應該設定為true。
batchSize:設定一次批次呼叫中包含的請求的最大數量,預設值為5。當待呼叫的請求超過這個設定時,即使未達到batchDelay中的設定時限,也立刻發出該批次請求。
batchDelay:設定一次批次呼叫的等待時限。預設值為1000(毫秒)。當等待時限超過這個設定時,即使未達到batchSize中的請求數量,也立刻發出該批次請求。
如此設定後,頁面中的每個Web Service請求都會套用批次呼叫。所以,對於單獨的一次調用,您應該將其優先級指定為高。
讓我們來看一個實例,先寫一個Web Service,其中有下述Web Method,兩個參數分別代表該任務的順序(這樣我們可以分辨任務執行的順序)以及優先權:
[WebMethod]
public string DoTask(int taskID, int priority)
{
if (priority < 0 || priority > 2)
throw new Exception("priority can only be 0, 1 or 2!");
return string.Format("Task (ID: {0}, Priority: {1}) finished.", taskID, priority);
}
然後按照開頭部分程式碼在web.config中啟用批次調用,並在頁面上新增WebRequestManager,不要忘了頁面上還需要一個ScriptManager,引用上面定義的Web Service: <atlas:ScriptManager ID="scriptManager" runat=" server">
<Services>
<atlas:ServiceReference Path="SampleService.asmx" />
</Services>
</atlas:ScriptManager>
新增HTML標記。其中按鈕用來引發批次調用,div用來顯示調用結果:
<input id="invokeTasks" type="button" value="Invoke Task Calls" onclick="return invokeTasks_onclick()" />
<div id="result"/>
最後是JavaScript腳本,呼叫Web Service:
function invokeTasks_onclick()
{
// clear the output
$('result').innerHTML = '';
DoTask(1, 2);
DoTask(1, 1);
DoTask(2, 0);
}
var taskID = 0;
function DoTask(times, priority)
{
for (var i = 0; i < times; ++i)
{
SampleService.DoTask(
taskID++,
priority,
{onMethodComplete: OnComplete, priority: priority }
);
}
}
function OnComplete(result)
{
$('result').innerHTML += result + "<br />";
}
注意到DoTask()方法接受兩個參數:times用來指定呼叫次數,priority用來指定優先權,並且我們利用了一個全域的變數taskID用來維護一個自增的請求順序。
在這個範例中,我們首先呼叫了一個低優先權的請求,然後一個中優先權的,最後兩個高優先權的。
由於高優先權不參與批次調用,所以您最先看到的是它們的返回:
由於中低優先級的總數為2個,尚未達到5 ,所以在3000毫秒的延遲過後才被發送:
您可以修改invokeTasks_onclick()方法中的呼叫順序以及呼叫數目,分析批次呼叫的實作方式。
該範例程式可以在此下載: