蛙蛙推薦:如何編寫異步的WebService(不是異步調用WebService)

如何編寫異步的WebService(不是異步調用WebService)

摘要:我們做webService的時候,如果在處理用戶請求的時候需要進行異步IO操作,在異步IO完成前會有一個線程在那裏同步等待,正在等待的請求太多的話會大大降低服務的吞吐量,asp.net2.0裏有異步的HttpHandler能解決這個問題,可.net2.0沒給弄一個異步的webservice,這就需要我們自己去實現了。

分析:.net處理webservice請求大致是這樣的
1、用SyncSessionlessHandler來接收客戶端的soap請求;
2、把這些文本的xml構建SoapMessage,SoapMessage裏包含SoapMethod及參數等信息。
3、根據uri來獲取請求的是哪個WebService,然後用反射取出該WebService裏包含WebMethodAttriube的方法。
4、用SoapMessage裏信息和反射出來的MethodInfo去匹配,並用反射的方式去Invoke Webservice那個類的方法。
5、把那個方法返回的值再序列化成Soap格式返回給客戶端。

當然只是大致分析,具體的處理還包含是否啓用事務,是否啓用Session,以及大量的請求驗證,緩存反射信息等操作。

在客戶端異步調用web服務端時候會使用AsyncSessionHandler和AsyncSessionlessHandler這兩個異步httphandler,但如果客戶端同步調用就不能使用了。

知道了原理之後,我們可以寫一個異步httphandler,獲取用戶請求構建SoapMessage,獲取參數信息後,去調用自己指定的方法,而不是默認要調用的方法,在我們指定的方法裏發送異步IO請求,在異步IO完成後,我們再構建原來方法的返回值,序列化成Soap格式,返回給客戶端,然後設置異步httphandler的IAsyncResult.IsCompleted爲true。

具體的部分我已經封裝好了,下面介紹一下步驟。
1、先設計好webservice,如下

using System;
using System.Web.Services;

namespace TestWS
{
    
public class UserInfo
    {
        
public int Age;
        
public DateTime Birthday;
        
public string Password;
        
public bool Sex;
        
public string Username;
    }

    
public class RegisterResult
    {
        
public string Description;
        
public int StatusCode;
        
public string Username;
    }

    [WebService(Namespace 
= "http://www.fetionmm.com/")]
    [WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]
    
public class Service1 : WebService
    {
        [WebMethod]
        
public RegisterResult RegisterUser(UserInfo userInfo)
        {
            var result 
= new RegisterResult();
            result.Username 
= userInfo.Username;
            result.StatusCode 
= 200;
            result.Description 
= "ok";
            
return result;
        }
    }
}

2、寫一個ashx文件,如下

using MySoapLib;

namespace TestWS
{
    
//這個類要繼承自SoapAsyncHandler,它會自動接收soap消息並調用匹配的方法
    
//然後要編寫和VirtualServiceUri所指向的webService有相同的方法,但返回值都是void,
    
//在對請求處理完成時構造返回值,再調用asynch.WriteResult來向調用者返回SOAP消息
    public class Handler1 : SoapAsyncHandler
    {
        
protected override string VirtualServiceUri
        {
            
get { return "/Service1.asmx"; }
        }

        
public void RegisterUser(UserInfo userInfo)
        {
            var result 
= new RegisterResult();
            result.Username 
= userInfo.Username;
            result.StatusCode 
= 200;
            result.Description 
= "ok";
            asynch.WriteResult(result);
        }
    }
}

3、編寫調用者,設置代理類的uri爲新的ashx,而不是默認的asmx,如下

using System;
using WSClient.localhost;

namespace WSClient
{
    
internal class Program
    {
        
private static void Main(string[] args)
        {
            Console.WriteLine(
"start");
            var service1 
= new Service1();
            service1.Url 
= "http://localhost:10514/Handler1.ashx";
            var userInfo 
= new UserInfo();
            userInfo.Username 
= "onlytiancai";
            userInfo.Password 
= "password";
            userInfo.Age 
= 25;
            userInfo.Birthday 
= DateTime.Parse("1983-01-01");
            userInfo.Sex 
= false;
            RegisterResult result 
= service1.RegisterUser(userInfo);
            Console.Write(
"name:{0},status:{1},desc,{2}", result.Username,
                          result.StatusCode, result.Description);
            Console.ReadKey();
        }
    }
}

具體的原理,大家看看代碼吧,再挑挑毛病。

代碼下載:

http://files.cnblogs.com/onlytiancai/AsyncWebService.zip

 

此文撤回,原來實現服務端的異步web服務有官方方法,我先去吃飯,回來再試試,汗了,白浪費哥們嘔心瀝血幾十載把代碼扣出來了。

http://www.microsoft.com/india/msdn/events/Inside%20ASP.NET%20Runtime.zip_

http://fhict.fontys.nl/Deeltijd/1JarigeStudies/CSA/Lesmateriaal/Week%202/Achtergrond/WebServicesTutorial.ppt

 

Server-Side Asynchronous Calls

         Can implement asynchronous design patterns in your Web service

                   Asynchronous Web method pattern

                   Custom pattern      

         Mitigate risk of operation timeout

         Perform lengthy operations on a different thread

         Client proxy usage doesn’t change

 

Asynchronous Web Methods

         WebServiceHandlerFactory

                   Default IHttpHandlerFactory assigned to process Web service extensions (*.asmx)

                   Uses reflection to determine if method to invoke is implemented synchronously or not

                   Returns appropriate IHttpHandler object to process the Web method request

 

Web Service Handlers

         System.Web.Services.Protocols

                   Contains (undocumented) handlers

                   Functionality varies based on session and asynchronous method implementation

         Handlers:

                   SyncSessionHandler

                   AsyncSessionHandler

                   SyncSessionlessHandler

                   AsyncSessionlessHandler

 

BeginXXX()/EndXXX() Methods

         Replace single Web method with asynchronous method pair

         Follow asynchronous design pattern for method signatures

 

         [WebMethod]

         public IAsyncResult BeginSleeper2(int mm, AsyncCallback cb, object state)

         {...}

        

         [WebMethod]

         public string EndSleeper2(IAsyncResult ar)

         {...}

 

         WSDL still exposes a single method for the pair

         Framework handles invocation of asynchronous methods

                   Frees service thread to handle other requests

                   EndXXX() is invoked by handler when framework receives callback

 

Custom Asynchronous Pattern

         Implement complex server-side threading behaviors

         Provide methods to query status and request results

         Provide storage of results for transmission on request

 

測試通過,我汗死。

using System;
using System.Web.Services;

namespace TestWS
{
    [WebService(Namespace 
= "http://www.fetionmm.com/")]
    [WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]
    
public class Service1 : WebService
    {
      
        [WebMethod]
        
public IAsyncResult BeginRegisterUser(UserInfo userInfo,AsyncCallback cb, object state)
        {
            RegisterUserDeleate d 
= RegisterUser;
            
return d.BeginInvoke(userInfo, cb, d);
        }

        
private delegate RegisterResult RegisterUserDeleate(UserInfo userInfo);
        
public RegisterResult RegisterUser(UserInfo userInfo) {
            RegisterResult result 
= new RegisterResult();
            result.Username 
= userInfo.Username;
            result.StatusCode 
= 200;
            result.Description 
= "ok";
            
return result;
        }

          [WebMethod]
        
public RegisterResult EndRegisterUser(IAsyncResult ar)
          {
              RegisterUserDeleate d 
= ar.AsyncState as RegisterUserDeleate;
              
return d.EndInvoke(ar);
          }

    }
}

發佈了183 篇原創文章 · 獲贊 4 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章