In both cases, there is such a different, the most troubled question is to respond to Fast.aspx's pages more than 4 seconds more than the original time. Although this example is our artificial, but this example shows When you have such a related response page is one of the worst situations. If you are slow in your application, you will affect the use of the CPU due to the slowness of action, in addition to adding more hardware devices, it seems to have no good way However, the slowed page of the application is slow because the operation of the Non-CPU-Bound is complete, the problem is not in the CPU power lack, the actually request enters the thread pool, so other requests must be queued until a thread freed.
If you are viewing the system's scalability, it is affected by the ASP.NET thread pool, so you have few choices. You can change the upper limit of the thread pool. As you can see, the default work thread and I / O thread The upper limit is 25. Of course, the upper limit is a relatively stupid approach. If you can find a good number to maintain the high utilization rate of the CPU and the request is delayed or rejected when the server is really very busy, then You are so lucky. The number of threads that keep the service really busy is not stationary, depending on the complexity of various factors such as demand and processing.
Another potential approach is to confirm that the system needs more and performs a Non-CPU-Bound request, and then assigning a unique thread to respond to the thread of the original thread pool to respond to additional requests. This is asynchronous processor .
Asynchronous processor
Although most of the ASP.NET pages and processing are responding from synchronous threads (from process-level thread pools), it is possible to create asynchronous requests. The asynchronous handler implements the IHTTPASYNCHANDLER interface. This interface is inherited in IHTTPHANDLER :
Public interface httpasynchandler: IHTTPHANDLER
{
IASYNCRESULT BEGINPROCESSREQUEST (HTTPContext CTX,
AsyncCallback CB,
Object obj);
Void EndProcessRequest (IASYNCRESULT AR);
}
Implementing this interface must implement two standards from IHTTPHandler. The first, BeginProcessRequest, is applied by the application class call instead of directly calling ProcessRequest. It will let the handlers initiate a new thread to deal with request and will return from the BeginProcessRequest method. Through a reference to verify the IASYNCRESULT instance, the purpose is to make the running time until the end. The other method is EndProcessRequest, which is called if the request processing is called, if it is necessary to clear any original resource. If you have done The job works under the .NET Framework, you should know the easiest and most recommended way to use asynchronous entrustment agents to perform asynchronous work. Call the asynchronous agent to perform the entrustment function by calling BeginInvoke implicit using threads from process-level thread pools. Using asynchronous commissioned to achieve asynchronous handlers actually be very straightforward, as shown in Figure 2.
<% @ Webhandler Language = "C #"
Class = "essentialaspdotnet.httppipeline.asynchandler"%>
Using system;
Using system.Web;
Using system.threading;
Using system.diagnostics;
Using system.reflection;
Namespace essentialaspdotnet.httpppipeline
{
Public Delegate Void ProcessRequestdeLegate (HTTPContext CTX);
Public class asynchandler: IHTTPASYNCHANDLER
{
Public Void ProcessRequest (HttpContext CTX)
{
System.Threading.Thread.Sleep (2000);
CTX.Response.output.write
"AsyncDelegate, threaded = {0}",
Appdomain.getCurrentThreadId ());
}
Public Bool IsReusable
{
Get {return true;}
}
Public IASYNCRESULT BEGINPROCESSREQUEST (HttpContext CTX,
AsyncCallback CB, Object Obj)
{
ProcessRequestDelegate PRG =
New processRequestDelegate (ProcessRequest);
// fire-and-forget
Return PRG.BEGINININVOKE (CTX, CB, OBJ);
}
Public Void EndProcessRequest (IASYNCRESULT AR)
{
}
}
}
Figure II
I implemented IHTTPASYNCHANDLER.BEGINPROCESSREQUEST call BeginInvoke on one of my ProcessRequestDelegate instance,
ProcessRequestDelegate has been initialized in my ProcessRequest method. This is valid on a separate thread, separating from the request thread.
Run the same pressure test Slow.aspx page, this time this time I use my new asyncDelegate.ashx handler instead of Fast.aspx, the result is as follows, the average response time fast.aspx is 4.14 seconds, asyncDelegate.ashx is 7.86 seconds, request number It is 957 times.
Disappointed, response time for Fast.aspx does not really improve. Because asynchronous delegate call does not create an asynchronous processor because it comes from the same CLR thread pool (response request). However, a major request thread does need to return to the thread pool, and another thread is taken out to perform asynchronous delegation, which means that this has a response to an additional empty thread harvest, so the handler is not used. You will get the same problem If you use threadpool.queueuserWorkItem to perform asynchronous request processing, think it is also the same way to get a thread. Use a custom thread asynchronous processor