Implement Asynchronous queue control for existing aspx requests

Source: Internet
Author: User

When An ASPX page request processing involves a lot of Io work and these Io resources are very limited, this page may cause a large number of threads to wait for processing when there are a large number of requests on the opposite side, so that the applicationProgramExcessive thread overhead affects the overall processing efficiency. in this case, we hope to use a queue mechanism to control the overhead of processing threads to achieve more efficient processing efficiency. therefore. NET provides ihttpasynchandler to solve these problems, but the problem is that implementing an ihttpasynchandler means you need to implement your own processing process and cannot implement the functions that have already been implemented. aspx for control. but through decompilation. netCodeNow we can implement an ihttpasynchandler to take over the existing. ASPX page for asynchronous processing without modifying the code of the existing page implementation.

From the Web configuration file of. net, Asp.net does not handle aspx by default, instead of ihttphandler, but system. Web. UI. pagehandlerfactory. Let's look at the decompilation code.

[Permissionset (securityaction. inheritancedemand, unrestricted = true), permissionset (securityaction. linkdemand, unrestricted = true)] public class pagehandlerfactory: ihttphandlerfactory2, ihttphandlerfactory {private bool _ isinheritedinstance; protected internal pagehandlerfactory () {This. _ isinheritedinstance = (base. getType ()! = Typeof (pagehandlerfactory);} Public Virtual ihttphandler gethandler (httpcontext context, string requesttype, string virtualpath, string path) {return this. gethandlerhelper (context, requesttype, virtualpath. createnonrelative (virtualpath), PATH);} ihttphandler ihttphandlerfactory2.gethandler (httpcontext context, string requesttype, virtualpath, string physicalpath) {If (this. _ isinheritedinstance) {return this. gethandler (context, requesttype, virtualpath. virtualpathstring, physicalpath);} return this. gethandlerhelper (context, requesttype, virtualpath, physicalpath);} Public Virtual void releasehandler (ihttphandler handler) {} private response gethandlerhelper (httpcontext context, string requesttype, virtualpath, string physicalpath) {page = buildmanager. createinstancefromvirtualpath (virtualpath, typeof (PAGE), context, true) as page; If (page = NULL) {return NULL;} page. templatecontrolvirtualpath = virtualpath; return page ;}}

From the decompilation code, we can see the hope. first, pagehandlerfactory can be inherited, while gethandler can be rewritten. With these two conditions, we can fully meet our needs. by inheriting pagehandlerfactory, you can directly process existing aspx files.

Implement ihttpasynchandler

Since gethandler of pagehandlerfactory can be rewritten, and ihttpasynchandler inherits ihttphandler, the process becomes much simpler. It may be returned directly by constructing an ihttpasynchandler.

 
Public class custompagefactory: system. web. UI. pagehandlerfactory {static custompagefactory () {g_taskqueue = new taskqueue (20);} public static taskqueue g_taskqueue; Public override ihttphandler gethandler (httpcontext context, string requesttype, string virtualpath, string path) {aspxasynchandler handler = new aspxasynchandler (base. gethandler (context, requesttype, virtualpath, PATH); Return handler ;}}

You can implement an ihttpasynchandler to repackage ihttphandler returned by pagehandlerfactory.

 
Public class handler: ihttpasynchandler {public aspxasynchandler (ihttphandler handler) {mhandler = handler;} private ihttphandler mhandler; Public iasyncresult inprocessrequest (httpcontext context, asynccallback CB, object extradata) {aspxasyncresult result = new aspxasyncresult (context, mhandler, CB); custompagefactory. g_taskqueue.add (result); return result;} public void endprocessrequest (iasyncresult result) {} public bool isreusable {get {return false;} public void processrequest (httpcontext context) {Throw new notimplementedexception ();}}

In this way, the httphandler for asynchronous processing is fully packaged. You only need to configure httphandler to Implement Asynchronous queue processing for the existing Aspx.

 
<Handlers> <Add name = "custompage" verb = "*" Path = "*. aspx" type = "webapp. Code. custompagefactory, webapp"/>  
Queue and thread control

In the process of processing, the thread pool is not used to complete the specific work. If each thread pool is called directly, the same problem is that the thread consumption caused by a large number of Thread Scheduling Problems affects the performance. therefore, in the beginprocessrequest method that implements ihttpasynchandler above, an iasyncresult is constructed and added to the queue. the implementation of this queue is relatively simple:

Public class taskqueue {public taskqueue (INT group) {mdispatchs = new list <dispatch> (Group); For (INT I = 0; I <group; I ++) {mdispatchs. add (new dispatch () ;}} private ilist <dispatch> mdispatchs; private long mindex = 0; private int getindex () {return (INT) system. threading. interlocked. increment (ref mindex) % mdispatchs. count;} public void add (aspxasyncresult aspasync) {If (aspasync! = NULL) {mdispatchs [getindex ()]. push (aspasync) ;}} class dispatch {public dispatch () {system. threading. threadpool. queueuserworkitem (onrun);} private queue <aspxasyncresult> mqueue = new queue <aspxasyncresult> (1024); Public void push (aspxasyncresult Aspar) {lock (this) {mqueue. enqueue (Aspar) ;}} private aspxasyncresult POP () {lock (this) {If (mqueue. count> 0) return mqueue. dequeue (); retur N null ;}} private void onrun (object state) {While (true) {aspxasyncresult asyncresult = POP (); If (asyncresult! = NULL) {asyncresult. Execute () ;}else {system. Threading. thread. Sleep (10 );}}}}}

To better control the thread, the queue is implemented by using multi-queue and multi-thread mechanism, that is, to specify the number of thread queues Based on the concurrency you need. Of course, this design is rigid and not flexible, if you want to design a flexible one, you can dynamically calculate the number of existing queue threads Based on the processing status and resource conditions of the current queue.

Iasyncresult implementation

Asynchronous return processing object implementation is also very simple, implementing an execute method is executed by the queue, after the execution is complete, the callback method is used to notify the processing is complete.

Public class handler: callback {bool m_iscompleted = false; private callback mhandler; private httpcontext mcontext; private asynccallback m_callback; Public callback (httpcontext context, ihttphandler handler, asynccallback CB) {mhandler = handler; mcontext = context; m_callback = CB ;}# region iasyncresult member public object asyncstate {get {return NULL ;}} public waitha Ndle asyncwaithandle {get {return NULL ;}} public bool completedsynchronously {get {return false ;}} public bool iscompleted {get {return m_iscompleted ;}# endregion public void execute () {try {mhandler. processrequest (mcontext);} catch {} finally {try {If (m_callback! = NULL) m_callback (this);} catch {}m_iscompleted = true ;}}}
Test Results

In order to verify the effectiveness of this implementation, a simple test is conducted. A web page accesses a logic service, while the connection pool has only 20 wired connections in the interaction process, if the current connection pool is empty, you must wait for other connections to be recycled. the test results are as follows:

    • Asynchronous processing is useless:

    • When asynchronous processing is used (fixed 15 threads ):

From the test results, there are a large number of request errors in the absence of asynchronous processing, while there is also a large amount of CPU resource consumption, the test results that use Asynchronous processing remain stable throughout the processing process. of course, at the same time, we need to reduce some processing capacity and high latency, but these can all achieve a better result by setting the scheduling thread.

Summary

From the test results, we can see that asynchronous httphandler and queue control can control thread processing in some fields to improve system stability and processing efficiency, more importantly, you can configure httphandler to process asynchronous requests to the existing Aspx. Of course, we do not need to configure it for all Aspx, only the aspx with a relatively high concurrency for some memory I/O operations is required.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.