蛙蛙推荐:如何编写异步的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.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文件,如下
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 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_
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);
}
}
}