3.motan之异步调用
一、什么是异步调用?
1.同步调用
方法间的调用,假设A方法调用B方法,A方法等待B方法执行完毕后才执行本身,这个同步调用,是具有阻塞式的调用,如果B方法非常耗时,那么整个方法的执行效率将会非常低;
2.异步调用
同样是方法间的调用,假设A方法调用B方法,不同的是A方法调用B方法后,B方法很快的返回给A方法个答复(这个答复不是执行完整个B方法的答复),A方法收到答复后就执行本身,这个是异步调用,不管B方法是否耗时,整体的效率都提升。
二、motan的异步调用入门
1.首先,以入门案例为基础案例改造:http://www.cnblogs.com/Json1208/p/8784906.html
2.motan-api工程HelloWorldService添加注解@MotanAsync
package com.motan.service;import com.weibo.api.motan.transport.async.MotanAsync;@MotanAsync public interface HelloWorldService {String hello(String name); }
3.motan-api添加maven插件build-helper-maven-plugin,用来把自动生成类的目录设置为source path
<build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>build-helper-maven-plugin</artifactId><version>1.10</version><executions><execution><phase>generate-sources</phase><goals><goal>add-source</goal></goals><configuration><sources><source>${project.build.directory}/generated-sources/annotations</source></sources></configuration></execution></executions></plugin></plugins></build>
编译时,Motan自动生成异步service类,生成路径为target/generated-sources/annotations/,生成的类名为service名加上Async,例如service类名为HelloWorldService.java,则自动生成的类名为HelloWorldServiceAsync.java。
另外,需要将motan自动生产类文件的路径配置为项目source path,可以使用maven plugin或手动配置,以上使用maven plugin方式。
这样,我们就能在eclipse中的source folder 中生成HelloWorldServiceAsync.java。
4.motan-client.xml配置的motan:referer标签中配置interface为自动生成的以Async为后缀的对应service类
<motan:referer id="helloWorldReferer" interface="com.motan.service.HelloWorldServiceAsync" directUrl="localhost:8002"/>
5.测试,先启动server,再启动client
public class Server {@SuppressWarnings({ "unused", "resource" })public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:motan-server.xml");System.out.println("server start...");} }log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start...
public class Client {@SuppressWarnings("resource")public static void main(String[] args) throws InterruptedException {ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:motan-client.xml"});HelloWorldServiceAsync async = (HelloWorldServiceAsync) ctx.getBean("helloWorldReferer");System.out.println(async.hello("motan"));} }log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. Hello motan!
最后再来看server的控制台,如果成功调用,会输出方法结果:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start... motan
三、motan异步调用详解
1.使用ResponseFuture接口来接收远程调用结果,ResponseFuture具备future和callback能力
①.将接口实现修改为:
package com.motan.service;public class HelloWorldServiceImpl implements HelloWorldService{@Overridepublic String hello(String name) {try {Thread.sleep(5000); System.out.println(name);System.out.println("等待5s后返回");} catch (InterruptedException e) {e.printStackTrace();}return "Hello " + name + "!";}}
②.修改客户端调用为:
package com.motan.client;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.motan.service.HelloWorldServiceAsync; import com.weibo.api.motan.rpc.ResponseFuture;public class Client {@SuppressWarnings("resource")public static void main(String[] args) throws InterruptedException {ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:motan-client.xml"});HelloWorldServiceAsync async = (HelloWorldServiceAsync) ctx.getBean("helloWorldReferer");ResponseFuture future = async.helloAsync("ResponseFuture");System.out.println(future.getValue());} }
注意:为了防止接口调用超时,消费端需要配置调用超时时间,在motan-client.xml中配置:
<motan:referer id="helloWorldReferer" interface="com.motan.service.HelloWorldServiceAsync" directUrl="localhost:8002" connectTimeout="8000" requestTimeout="8000"/>
③.启动服务端
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start...
④.启动客户端
等待5s后服务端控制台打印:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start... ResponseFuture 等待5s后返回
客户端控制台打印:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. Hello ResponseFuture!
2.使用FutureListener监听,该监听器可以监听到接口是否成功调用,可以很灵活的判断如果成功调用在输出相关调用返回信息
虽然ResponseFuture带有isDone和isSuccess,但是经过测试,isDone和isSuccess并没办法在异步调用后用于判断,而是得配合FutureListener一起使用:
①.service实现不变,仍然是带有休眠的效果:
package com.motan.service;public class HelloWorldServiceImpl implements HelloWorldService{@Overridepublic String hello(String name) {try {Thread.sleep(5000);System.out.println(name);System.out.println("等待5s后返回");} catch (InterruptedException e) {e.printStackTrace();}return "Hello " + name + "!";}}
②.使用FutureListener监听server端是否执行成功
package com.motan.client;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.motan.service.HelloWorldServiceAsync; import com.weibo.api.motan.rpc.Future; import com.weibo.api.motan.rpc.FutureListener; import com.weibo.api.motan.rpc.ResponseFuture;public class Client {@SuppressWarnings("resource")public static void main(String[] args) throws InterruptedException {ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:motan-client.xml"});HelloWorldServiceAsync async = (HelloWorldServiceAsync) ctx.getBean("helloWorldReferer");FutureListener listener = new FutureListener() {@Overridepublic void operationComplete(Future future) throws Exception {System.out.println("async call "+ (future.isSuccess() ? "sucess! value:" + future.getValue() : "fail! exception:"+ future.getException().getMessage()));}};ResponseFuture future1 = async.helloAsync("motan FutureListener...");future1.addListener(listener);} }
③.测试
首先,执行server端启动程序:
package com.motan.server;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Server {@SuppressWarnings({ "unused", "resource" })public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:motan-server.xml");System.out.println("server start...");} }log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start...
接着,启动client端启动程序:
等待5s之后,server控制台输出:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start... motan FutureListener... 等待5s后返回
再来看client控制台输出:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. async call sucess! value:Hello motan FutureListener...!
注意:在server端休眠的时候,client端是阻塞着的,由于我们超时时间跟上方一致配置的是8s,所以并不会超时,导致client一致阻塞,我们试着把超时实际调为3s(比server休眠时间短):
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd"><!-- 具体referer配置。使用方通过beanid使用服务接口类 --><motan:referer id="helloWorldReferer" interface="com.motan.service.HelloWorldServiceAsync" directUrl="localhost:8002" connectTimeout="3000" requestTimeout="3000"/> </beans>
重新启动server应用程序,server控制台输出:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start...
还未到休眠5s执行结束,client端就抛出一个异常:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. async call fail! exception:error_message: com.weibo.api.motan.rpc.DefaultResponseFuture task cancel: serverPort=localhost:8002 requestId=1597643022347010049 interface=com.motan.service.HelloWorldService method=hello(java.lang.String) cost=3042, status: 503, error_code: 10001,r=null
最后,server端才把休眠之后的消息打印:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. server start... motan FutureListener... 等待5s后返回
说明:client使用监听器监听server是否执行完毕,若server实际执行业务的时间在client端配置的接口请求超时时间之内,那么client请求后会一致阻塞着,直到server实际业务执行完成返回;
若server实际执行业务的时间大于client端配置的接口请求超时时间,那么一旦到达超时时间,直接抛出异常。
转载于:https://www.cnblogs.com/Json1208/p/8799370.html
3.motan之异步调用相关推荐
- springboot 多线程_SpringBoot异步调用@Async
一. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 二. 如何实现异步调用 ...
- C++多线程:package_task异步调用任何目标执行操作
文章目录 描述 函数成员及使用 总结 我们上一篇描述关于C++多线程中的异步操作相关库( async和 promise),本节将分享c++标准库中最后一个多线程异步操作库 package_task的学 ...
- springboot之异步调用@Async
引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3. ...
- 异步调用WCF的方法需要小心的地方
直接使用下面的代码,由于client对象占用的资源没有被释放,会导致内存泄露 GetSimServiceReference.GetSimServiceClient client = new GetSi ...
- 关于webservice的异步调用简单实例
于webservice的异步调用简单实例 无论在任何情况下,被调用方的代码无论是被异步调用还是同步调用的情况下,被调用方的代码都是一样的, 下面,我们就以异步调用一个webservice 为例作说明. ...
- Spring Boot 中使用@Async实现异步调用,加速任务执行!
欢迎关注方志朋的博客,回复"666"获面试宝典 什么是"异步调用"?"异步调用"对应的是"同步调用",同步调用指程序按照 ...
- Spring Boot 异步请求和异步调用
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.Spring Boot中异步请求的使用 1.异步请求与同步请求 ...
- xml提示无法连接到远程服务器,异步调用WebService时,如何捕捉“无法连接远程服务器”异常...
在winform窗体中调用webservice,过程如下: ①Form1中弹出Form2 Form2 form2 = new Form2(); form2.ShowDialoag(); ②Form2中 ...
- JavaScript异步调用的发展历程
同步与异步 通常,代码是由上而下依次执行的.如果有多个任务,就必须排队,前一个任务完成,后一个任务才能执行.这种连续的执行模式就叫做同步. a(); b(); c(); 复制代码 上面代码中,a.b. ...
最新文章
- strcpy.strcmp.strlen.strcat函数的实现
- 使用python库matplotlib绘制不同的图表
- 【Stimulsoft Reports Flex教程】从代码渲染报表
- Django的静态文件路径设置对比
- qt 实现html 编辑器,基于QT的HTML编辑器的设计与实现.doc
- windows端口备忘
- Java基础---接口是啥?
- C++STL笔记(一):STL综述
- 【QT】无需写connect代码关联信号和槽函数
- 创建连接数据库(DBLink)
- 数据挖掘关联规则挖掘之FpGrowth算法
- 视频教程-初级学习ArcGIS Engine视频课程-C#
- 【ManageEngine】如何利用好OpManager的报表功能
- SAP中英文转换--中文转英文
- 2.模仿小米通讯录的快速索引demo
- 智慧社区的现状分析及发展前景
- 解决UE4打包Android报错app:packageDebug FAILED的一个土方法
- 谈一下我是如何从使用json-lib到投入fastjson的怀抱....
- ZZNUOJ_C语言1046:奇数的乘积(完整代码)
- 史上最BT的真实案例集