IIS可以對ASP.NET站點進行一個資源控制,包括使用的CPU,處理進程數等.但如果想對某些動態頁面進行一個資源限制,只允許固定線程數量來處理某些動態請求,而不至於在某些情況個別的動態請求把整個站的資源都占光了.對於這么小的粒度控制顯然不適合由IIS來做,這個時候就可以通過asp.net提供IHttpAsyncHandler來解決這種事情.
處理結構
由於Asp.net提供了異步處理Handler,所以可以在Handler的Begin處理方法中把具體對象存放到隊列中,然后根據實際業務的需要來配置1-N個線程來處理相關請求.

IHttpAsyncHandler
public interface IHttpAsyncHandler : IHttpHandler
{
/// <summary>Initiates an asynchronous call to the HTTP handler.</summary>
/// <returns>An <see cref="T:System.IAsyncResult" /> that contains information about the status of the process.</returns>
/// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests. </param>
/// <param name="cb">The <see cref="T:System.AsyncCallback" /> to call when the asynchronous method call is complete. If <paramref name="cb" /> is null, the delegate is not called. </param>
/// <param name="extraData">Any extra data needed to process the request. </param>
IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
/// <summary>Provides an asynchronous process End method when the process ends.</summary>
/// <param name="result">An <see cref="T:System.IAsyncResult" /> that contains information about the status of the process. </param>
void EndProcessRequest(IAsyncResult result);
}
從代碼來看IHttpAsyncHandler也是從IHttpHandler派生下來,並提供了Begin和End相關方法.
對已有頁面進行異步封裝
如果經常用IHttpHandler的朋友應該比較清楚這東西用於描述一個頁面請求的,包括我們的aspx,而aspx默認處理的則是一個IHttpHandlerFactory實現System.Web.UI.PageHandlerFactory.通簡單地繼承System.Web.UI.PageHandlerFactory就可以讓原來的aspx請求返回對應的異步的HttpHandler.
public class CustomPageFactory : System.Web.UI.PageHandlerFactory
{
static CustomPageFactory()
{
}
public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
{
AspxAsyncHandler handler = new AspxAsyncHandler(base.GetHandler(context, requestType, virtualPath, path));
return handler;
}
}
PageFactory實現后只需要簡單地配置一個web.config文件就可以讓現有的aspx處理由異步Handler來處理.
<handlers> <add name="custompage" verb="*" path="*.aspx" type="WebApp.Code.CustomPageFactory,WebApp"/> </handlers>
隊列化處理
制定隊列的目的非常簡單就是有序可控地去處理一些工作,可以通過BeginProcessRequest的執行把請求先存放到了列中
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
AspxAsyncResult result = new AspxAsyncResult(context, mHandler, cb);
G_TaskQueue.Add(result);
return result;
}
制定線程處理
可以根據實際情況開啟1-N個線程來處理隊列中的工作.
private void OnRun(object state)
{
while (true)
{
AspxAsyncResult asyncResult = Pop();
if (asyncResult != null)
{
asyncResult.Execute();
}
else
{
System.Threading.Thread.Sleep(10);
}
}
}
以上是固定線程去進行處理,但這樣的設計不好的地方就是沒有請求的時候線程會不停地做sleep工作,其實可以根據實際情況使用線程池來完成,具體就看情況來設計了.
總結
通過以上設計就可以輕易地對某些頁面請求進行一個資源控制.如果比較關心具體實現的朋友可以查看
