如何編寫異步的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();
}
}
}
具體的原理,大家看看代碼吧,再挑挑毛病。
代碼下載:
http://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);
}
}
}