在上一篇文章中《记一次.NET HttpHandler接口性能优化过程》解决了同一客户端并发请求问题之后,IHttpHandler接口仍然是同步的模式,我们需要改成异步的模式,并将登录接口和业务接口拆开来,分别实现IRequiresSessionState和IReadOnlySessionState,已提高效率。这里需要思考两个问题:第一个问题是兼容:接口的修改需要考虑兼容性问题,原有接口建议不做改动;第二个问题是要考虑如何在前端代码不做任何改动的前提下,进行接口方法的重构。目的是做到接口的完美升级。
建立一个Handler工厂类,实现IHttpHandlerFactory接口,在GetHandler方法内区分登录接口和业务接口,将这个EatsunMobileServiceHandler工厂类作为新接口的入口。
public class EatsunMobileServiceHandler : IHttpHandlerFactory { public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { //...... // 区分登录接口和业务接口Handler if (action == "LOGIN") { //登录 return new EatsunMobileNewLoginHandler(param); } return new EatsunMobileNewHandler(param); } public void ReleaseHandler(IHttpHandler handler) { } }新建一个EatsunMobileNewLoginHandler类,实现IHttpHandler和 IRequiresSessionState,实现IRequiresSessionState的原因是现有登录逻辑本身需要读写Session ;而对于同一个客户端,登录业务本身不会有多个请求并发访问的情况。
public class EatsunMobileNewLoginHandler : IHttpHandler, IRequiresSessionState { public bool IsReusable { get { return false; } } public EatsunMobileNewLoginHandler(JSONObject param) { _param = param; } public void ProcessRequest(HttpContext context) { //登录方法,读写Session Request(context); } }继承新建的异步基类:HttpAsyncHandler
public class EatsunMobileNewHandler : HttpAsyncHandler { private JSONObject _param { get; set; } public EatsunMobileNewHandler(JSONObject param) { _param = param; } public bool IsReusable { get { return false; } } public override void BeginProcess(HttpContext context) { //具体业务逻辑 Request(context); EndProcess(); } }HttpAsyncHandler基类实现IHttpAsyncHandler、IAsyncResult异步接口和IReadOnlySessionState只读session接口,业务逻辑只需要读取session,所以这个只需要基层IReadOnlySessionState,已获得同一客户端并发请求情况下更好的性能表现。
public abstract class HttpAsyncHandler : IHttpAsyncHandler, IAsyncResult, IReadOnlySessionState { private bool _completed; private Object _state; private AsyncCallback _callback; private HttpContext _context; public object AsyncState { get { return _state; } } public WaitHandle AsyncWaitHandle { get { throw new NotImplementedException(); } } public bool CompletedSynchronously { get { return false; } } public bool IsCompleted { get { return _completed; } } public bool IsReusable { get { return false; } } public abstract void BeginProcess(HttpContext context); public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { _callback = cb; _context = context; _completed = false; _state = this; ThreadPool.QueueUserWorkItem(new WaitCallback(DoProcess), this); return this; } public void EndProcessRequest(IAsyncResult result) { } public void EndProcess() { if (!_completed) { try { _completed = true; if (_callback != null) _callback(this); } catch (Exception) { } } } private static void DoProcess(object state) { HttpAsyncHandler handler = (HttpAsyncHandler)state; handler.BeginProcess(handler._context); } public void ProcessRequest(HttpContext context) { //row new NotImplementedException(); } }
本章内容对原有IHttpHandler接口实现方法的重构,采用IHttpAsyncHandler异步的方式重新实现;并拆分出不需要写session的业务接口方法,实现IReadOnlySessionState接口,已达到同一客户端并发请求更好的性能表现。