赞
踩
目前成熟的RPC框架都会支持异步调用、异步监听、callback调用,今天我们来聊一聊这三种异步方式的方法及注意事项。
异步调用
有一个功能需要调用三个接口来实现业务需求,这三个接口耗时如下:A接口耗时400ms,B接口耗时200ms,C接口耗时700ms。
如果使用普通的同步调用方式,那么完成这个功能的总耗时为A+B+C=1300ms,如果采用异步调用,那么总耗时则是最长的那个接口的耗时,即700ms。示例代码如下:
- String resultA = service.testStrA("A");//发起一次调用,此时返回null
- ResponseFuture<String> futureA = RpcContext.getContext().getFuture();
- //得到第一次调用的Future
- String resultB = service.testStrA("B");//发起二次调用,此时返回null
- ResponseFuture<String> futureB = RpcContext.getContext().getFuture();
- //得到第二次调用的Future
- String resultC = service.testStrA("C");//发起三次调用,此时返回null
- ResponseFuture<String> futureC = RpcContext.getContext().getFuture();
- //得到第三次调用的Future
- //一定要调用get方法获取结果,否则会造成结果未被消费而导致内存溢出
- try {
- resultA = futureA.get();//可能会抛出异常
- }catch (Throwable e){
-
- }
- try {
- resultB = futureB.get();//可能会抛出异常
- }catch (Throwable e){
-
- }
- try {
- resultC = futureC.get();//可能会抛出异常
- }catch (Throwable e){
-
- }
RPC的异步调用是指客户端发起请求之后,不必等待获取结果,二是返回null值,同事可以获取一个Future对象,然后从Future中去获取结果,如代码所示。这样客户端在调用的时候不需要启动多个现成就可以并行调用多个远程服务接口。
异步监听
有时候我们发起一个调用请求之后,并不想通过Future的get获取结果,因为get的时候是阻塞的,而是希望调用请求之后可以去做其他事情,通过一个监听去监测,当有结果返回的时候直接获取结果,然后进行逻辑处理。比如下面的代码示例,有一个监听类TestResponseListener,它里面的handleResult方法负责处理结果数据。
- public class TestResponseListener implements ResponseListener {
- public void handleResult(Object result){
- //收到回调结果,进行业务处理
- }
- public void catchExceptio(Throwable e){
- //发生异常的处理
- }
- }
- <bean id="ResponseListener" class="com.**.listenner.TestResponseListener"/>
- <xx:consumer onreturn="responseListener" async="true"/><!--设置异步 并且有回调监听器-->
发送请求后不需要在调用getFuture方法。当有结果返回的时候,会自动调用事先注入好的TestResponseListener方法,发起异步调用的示例代码如下:
- String result1 = service.testStr("Test");//发起一次调用,此时返回null
- //不再需要调用getFuture方法,等待有结果返回,会自动调动TestResponseListener里的方法handleResult
注意:我们在使用异步监听的时候,建议最好限制发送的频率,发送太快会导致内存溢出等问题。
callback调用
RPC是以TCP全双工的协议进行通信的,基于长连接,服务端便具备了可以“调用”客户端callback函数的能力。有的RPC框架也会支持callback调用方式,它的使用方式如下:
step1,定义一个callback函数,增加一个Callback类型的方法参数。
- public interface HelloService{
- public void callBackString(String request, Callback<String> resultListener);
- }
step2,当客户端调用的时候注入一个Callback对象实例。
- Callback callback = new Callback<String>() {
- public void notify(String result) {
- System.out.println("notify callback string" + result);;
- }
- };
- service.callBackString("hello", callback);//客户端每次使用同一个Callback对象,服务端也得到了用一个Callback对象
step3,在服务端的代码里面,实现对callback的调用。
- public class HelloServiceImpl implements HelloService {
-
- public void callBackString(String request, Callback resultListener) {
- resultListener.notify("callback from server");
- }
- }
如果在服务端接口里面完成一个业务逻辑功能有3个过程,那么这3个过程中可以分别调用callback方法,形成“一次调用,多次通知”的机制,这一点在异步监听中是没有办法实现的,异步回调更像是“一次性买卖”。在高并发场景下建议使用异步监听的方式,因为callback方式客户端会对Callback实例的个数有限制。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。