蛙蛙推荐:如何编写异步的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();
        }
    }
}

具体的原理,大家看看代码吧,再挑挑毛病。

代码下载:

https://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);
          }

    }
}

posted @ 2009-02-28 12:57  蛙蛙王子  Views(5124)  Comments(15Edit  收藏  举报