`
elicer
  • 浏览: 131229 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Web Service 异步 service call 概念及 实例

阅读更多
在旧的基于JAX-RPC的webservice编程model中,是不支持异步的service 调用的,在最新的Jax-ws webservice 编程model中,加入了对webservice的异步调用的支持。
首先我来讲一下它的原理,大家不要以为在异步的调用下,从client到server 之间的soap message 流也是异步的,其实不是,Soap/Http 协议在同步跟异步的调用下是一样的,都是客户端的service在运行时打开一个connectin,发送请求,然后接收返回,这些都在同一个connection中。这种方式对我们有什么影响呢? 从客户端程序的角度来讲,没有影响,客户端的编程模型是由WSDL中的messages跟port types 来定义的,只要这些东西没有改变,request 跟response是不是在同一个Tcp/ip 的session 中来发送对与我们来说没由影响,然后从架构跟资源的角度来讲,对我们的影响就大了,把连接层的资源跟应用层的程序运行状态绑定起来是由许多弊端的,假如在异步调用时,程序运行出现了异常,将会导致连接层的资源被一直占用,这样会极大的影响我们程序的,稳定性,可靠性,资源的使用跟性能。
所以WebSphere Application Server V7提供了一个简单的实现,能够实现真实的异步soap Message,下面我们会详细讲解。

当前Jax-ws 提供了两种编程模型。
1.Polling client
2.CallBack client
下面我们分别就这两种编程模型进行讲解。
当你启用了异步调用功能时,当你用工具生成stub时,Jax-ws会给你每个operation 生成三个方法

a.An synchronous method
b.An asynchronous polling method
c.An asynchronous callback method
以下是一个生成的client-side Interface example
import java.util.concurrent.Future;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;

import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.Response;
import javax.xml.ws.ResponseWrapper;
@WebService(name = "HelloMessenger", targetNamespace =
"http://hello.itso/")
@XmlSeeAlso({
ObjectFactory.class
})
public interface HelloMessenger {
@WebMethod(operationName = "sayHello")
@RequestWrapper(localName = "sayHello", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHello")
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHelloResponse")
//Polling clients
public Response<SayHelloResponse> sayHelloAsync(
@WebParam(name = "arg0", targetNamespace = "")
String arg0);
@WebMethod(operationName = "sayHello")
@RequestWrapper(localName = "sayHello", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHello")
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHelloResponse")
// Call back clients
public Future<?> sayHelloAsync(
@WebParam(name = "arg0", targetNamespace = "")
String arg0,
@WebParam(name = "asyncHandler", targetNamespace = "")
AsyncHandler<SayHelloResponse> asyncHandler);
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "sayHello", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHello")
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace =
"http://hello.itso/", className = "itso.hello.SayHelloResponse")
//同步clients
public String sayHello(

@WebParam(name = "arg0", targetNamespace = "")
String arg0);
}


下面来详细讲述polling clients:
在这种异步模式下,当异步clients调syHelloAsync 方法,将会返回一个response object, 这个response Object 提供了一些方法来让你查询是否response已经返回,是否取消一个response,以及取得返回的response.如以下实例代码,你可以用sayHelloAsync .isDone来检查是否response已经返回。用sayHelloAsync .get()来取得返回的一个包装过的对象(SayHelloResponse),里面包含真实的返回值。

import javax.xml.ws.Response;
import itso.hello.HelloMessenger;
import itso.hello.HelloMessengerService;
import itso.hello.SayHelloResponse;
public class HelloAsyncPollingClient {
public static void main(String... args) throws Exception {
HelloMessengerService service = new HelloMessengerService();
HelloMessenger port = service.getHelloMessengerPort();
Response<SayHelloResponse> sayHelloAsync =
port.sayHelloAsync("Thilde");
//判断是否已经返回
while ( ! sayHelloAsync.isDone() ) {
// Do something useful for now
}
// Web service endpoint has now responded:
//取得包装过的返回对象
SayHelloResponse sayHelloResponse = sayHelloAsync.get();
//取得真实返回值
String message = sayHelloResponse.getReturn();

System.out.println(message);
}
}



Callbacking 模型的client 示例代码如下:
import itso.hello.HelloMessenger;
import itso.hello.HelloMessengerService;
import itso.hello.SayHelloResponse;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
public class HelloAsyncCallbackClient {
public static void main(String... args) throws Exception {
HelloMessengerService service = new HelloMessengerService();
HelloMessenger port = service.getHelloMessengerPort();
port.sayHelloAsync("Teresa", new AsyncHandler<SayHelloResponse>()
{
public void handleResponse(Response<SayHelloResponse> res) {
try {
SayHelloResponse response = res.get();

String message = response.getReturn();
System.out.println(message);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

由以上代码可知,callback类型的client要传入一个javax.xml.ws.AsyncHandler类型的匿名内部类,当soap Message 到达时,Jax-ws会调handleResponse这个方法来处理response.
以上就时Polling Client 跟Callback型的异步client的概念及使用示例,开始我也讲过,实际上这种所谓的异步调用有很大的弊端的。在最新的websphere  V7上提供一种解决方案。提供了一种真实的异步message的交换方式。在使用时你需要给client-side proxy配置一个特别的属性,示例如下:

Map<String, Object> requestContext =
((BindingProvider)port).getRequestContext():
// Configure the client for wire-level asynchronous message exchange
requestContext.put("com.ibm.websphere.webservices.use.async.mep",
true);


当你启用这种异步message交换机制时,client端会在request发出后在一个单独的channel上来监听和接收response message.当然,client在发出request时,会使用WS-Addressing 来向server提供 ReplyTo endpoint reference(ERP),当请求发出去以后当前的这个connection就会关闭,当servicer处理完请求时,它会根据client端提供的ERP(ReplyTo endpoint reference)重新初始化一个connection 来发送一个response.
当然了,这种机制也有弊端就时可移植性太差,只能在Websphere V7上使用。
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics