作者: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
$('resul
t').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()方法中的調用順序以及調用數目,分析批量調用的實現方式。
該示例程序可以在此下載:http://www.cnblogs.com/Files/dflying/BatchingCallsDemo.rar