`
gh_aiyz
  • 浏览: 40098 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Missian指南六:异步客户端使用指南

阅读更多

重要:Missian刚刚更新到0.31,新增了Future风格的回调方式。

 

Missian没有绑定spring,但是强烈推荐配合spring一起使用。异步客户端由于需要调用BeanLocator去寻找回调的 Bean,如果配合Spring使用,可以直接使用SpringLocator(BeanLocator的唯一实现),否则需要自己实现。

 

使用异步客户端需要注意一点:由于是异步调用,所以一个远程方法的返回值永远是null(如果不是void的话)或者是原生数据类型的默认值。一段时间后(比如100毫秒)后客户端收到这个返回值,会去找到相应的回调对象进行调用。

 

异步的优势是:在调用的期间我们不需要像同步调用一样有一个线程一直在等着它的返回值,而是调用完即可返回释放线程,当客户端接受到返回值后会进行 回调,业务流程可以继续往下执行。不要小看这个等待的时间,假如A服务调用了一个跨机房的服务或者一个重型的服务B,那么B的响应时间可能是100毫秒甚 至更多,那么可以想象在高并发的情况下,可能A服务的全部线程都耗死在无穷的等待上了。

 

我们还是先看看如何配合Spring来使用Missian异步客户端。

 

步骤一:给Hello.hello(String, int)创建一个回调类

注意和0.2x相比,这里有比较大的不同:

public class HelloCallback {
	public void hello(String returnValue) {
		System.out.println(returnValue);
	}
}

这个类的方法要和Hello接口的方法一一对应,Hello中所有方法(除了返回值为void的方法)都应该有一个回调方法,回调方法名和Hello接口中对应的方法名一样,而且只接受一个参数,参数类型和对应方法的返回值一致。

 

例如,Hello有一个hello(String, int)方法的返回值是String类型,那么要求HelloCallback必须有一个hello(String)的方法。

 

 

步骤二:修改Hello接口,用注解的方法声明回调Bean

这里和0.21前的版本也有所不同,以前这个注解是用在方法上的,现在直接用在接口上,所以一个接口只需要注解一次了。

@CallbackTarget("helloCallback")
public interface Hello {
	public String hello(String name, int age);
}

 

步骤三:在Spring配置文件中配置这个回调Bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- your callback bean, missian client will invoke its execute() method when received the returned object -->
	<bean id="helloCallback" class="com.missian.example.bean.HelloCallback">
	</bean>
</beans>

 

步骤四:在Spring中创建AsyncMissianProxyFactory

	<bean id="asyncMissianProxyFactory" class="com.missian.client.async.AsyncMissianProxyFactory" init-method="init" destroy-method="destroy">
		<constructor-arg >
			<bean class="com.missian.common.beanlocate.SpringLocator"/>
		</constructor-arg>
	</bean>

这里我们使用的是AsyncMissianProxyFactory的最简单的构造函数,只接受一个BeanLocator。这时候默认创建一个4 个线程的线程池用来处理回调逻辑,1个线程用来处理IO,需要指定线程数,或者将一个已经存在的线程池传入,可以参考其它几个构造函数:

public AsyncMissianProxyFactory(BeanLocator callbackLoacator, ExecutorService threadPool,  int callbackIoProcesses, boolean logBeforeCodec, boolean logAfterCodec, NetworkConfig networkConfig) {}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, ExecutorService threadPool,  int callbackIoProcesses, boolean logBeforeCodec, boolean logAfterCodec){}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, ExecutorService threadPool) {}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, int threadPoolSize, int callbackIoProcesses, boolean logBeforeCodec, boolean logAfterCodec) {}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, ExecutorService threadPool, NetworkConfig networkConfig) {}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, int threadPoolSize, int callbackIoProcesses, boolean logBeforeCodec, boolean logAfterCodec, NetworkConfig networkConfig) {}
public AsyncMissianProxyFactory(BeanLocator callbackLoacator, int threadPoolSize){}

假如在服务器里使用Missian客户端,可以考虑将服务器主线程池传入给AsyncMissianProxyFactory,共享线程池。 

 

步骤五:实现异步调用

 

	public static void main(String[] args) throws IOException {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/missian/example/client/async/withspring/applicationContext-*.xml");
		//actually you can inject AsyncMissianProxyFactory into any other beans to use it.
		//we just show how AsyncMissianProxyFactory works here.
		AsyncMissianProxyFactory asyncMissianProxyFactory = (AsyncMissianProxyFactory)context.getBean("asyncMissianProxyFactory");
		Hello hello = (Hello)asyncMissianProxyFactory.create(Hello.class, "tcp://localhost:1235/hello");
		long time = System.currentTimeMillis();
		for(int i=0; i<10000; i++) {
			hello.hello("gg", 25);	
		}
		System.out.println(System.currentTimeMillis()-time);
	}

 你可以清楚地看到,所有的请求都发送出去之后,返回值陆续返回并回掉了HelloCallback。

和同步的客户端一样,可以使用http协议发送数据:

Hello hello = (Hello)asyncMissianProxyFactory.create(Hello.class, "http://localhost:1235/hello");

但目前比较遗憾的是,还不能够支持异步调用Hessian服务。  

另外需要说明的是,这个直接从Context里面取出AsyncMissianProxyFactory只是用来演示异步调用的用法;正常的做法应该是将AsyncMissianProxyFactory注入到我们需要使用它的Bean。


===============0.31.新增功能分割线===================

 

如何为重载方法都实现回调?

比如以下两个方法都需要回调:

public interface Hello {
    String hello(String name, int age, String country);
    String hello(String name, int age);
}

 按照上面所说的,他们的回调方法都映射到:

void hello(String);

 这样会造成回调错误,因此需要使用一个注解来说明回调方法名:

@CallbackTarget("helloCallback")
public interface Hello {
	@CallbackTargetMethod("hello0")
	public String hello(String name, int age, String country);

	@CallbackTargetMethod("hello1")
	public String hello(String name, int age);
}

 对应的,回调类的实现:

public class HelloCallback {
	public void hello0(String returnValue) {
		System.out.println(returnValue);
	}
	public void hello1(String returnValue) {
		System.out.println("hello1:"+returnValue);
	}
	
}

 注意如果不使用注解,系统寻找默认的方法。注解同样也可以用于非重载的方法。

 

另外一种回调的实现

如果不希望使用注解,那么还有另外一种方式可供选择:

如果服务器端的方法是:

String hello(String name, int age);

 那么客户端的接口可以写成(注意,Missian不要求服务器端和客户端使用同一个接口类,甚至接口名都可以不同,而只要求方法名及参数必须匹配):

public interface Hello {
	public String hello(String name, int age, Callback cb);
}

 调用时:

Hello hello = (Hello)factory.create(Hello.class, "http://localhost:1235/hello");
Callback cb = ......
hello.hello("name", 80, cb);

 即可以异步调用成功。

 

Future风格的异步实现

我个人非常喜欢Future这种方法,在Mina中就有大量的使用。同样Missian也提供了这样一个能力。提供了一个AysncFuture,即可以通过get()变成同步,也可以通过addListner()来监听,一旦返回值到达,就会出发监听器。

 

如果服务器端的方法是:

String hello(String name, int age);

 那么客户端的接口可以写成(注意,Missian不要求服务器端和客户端使用同一个接口类,甚至接口名都可以不同,而只要求方法名及参数必须匹配):

public interface Hello {
	public AysncFuture<String> hello(String name, int age, Class<String> returnType);
}

 调用时:

Hello hello = (Hello)factory.create(Hello.class, "http://localhost:1235/hello");
Async<String> future = hello.hello("name", 80, String.class);

 如果想阻塞直到数据返回,那么:

String value = future.get();
System.out.println(value);

 如果想通过监听器实现事件驱动:

AsyncListener listener = ....
future.addListener(listener);
 

 

 

 

 

 

 

分享到:
评论
8 楼 sooxin 2012-07-23  
沉年老东西,问题一堆,实在不敢用。
放入tomcat
警告: EXCEPTION :
java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Buffer.java:474)
at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)
at org.apache.mina.core.buffer.AbstractIoBuffer.get(AbstractIoBuffer.java:492)
at com.missian.common.io.IoBufferInputStream.read(IoBufferInputStream.java:44)
at com.caucho.hessian.io.HessianInputFactory.readHeader(HessianInputFactory.java:74)
at com.missian.server.handler.MissianSkeleton.invoke(MissianSkeleton.java:142)
at com.missian.server.handler.MissianHandler.messageReceived(MissianHandler.java:61)
7 楼 shuibingfy 2011-01-17  
shuibingfy 写道
请教下楼主,如果用Future方式,用get同步调用,如何设置超时时间呢?
如果Future方式,又在哪里设置是否长连接呢?

哦,明白了
用get(long timeout, TimeUnit unit)就行了吧
至于异步的长连接问题,是不是只要不调用AsyncMissianProxyFactory.destroy(),就可以认为是长连接?
6 楼 shuibingfy 2011-01-14  
请教下楼主,如果用Future方式,用get同步调用,如何设置超时时间呢?
如果Future方式,又在哪里设置是否长连接呢?
5 楼 zhangcheng 2011-01-04  
楼主搞的这个东西,我最近也有这个打算。我们的一个项目中使用了hessian,但是同步的http请求,效率实在是不怎么样。所以打算用mina作为服务器端,但是又不想改变客户端的调用方式,用stub的rpc。所以楼主将这两个好项目结合在一起,很不错。决定试用一下。
4 楼 gh_aiyz 2010-12-15  
yanwt 写道
我不是这个意思,我是说我一次发了50个请求,如:
  for (int i = 0; i < 50; i++) {
            AsyncFuture<String> future = async.asyncHello(time + "gg", i, String.class);
            resultList.add(future);
            System.out.println("testasync:"+System.currentTimeMillis());
        }
后台HelloImpl中的
public String asyncHello(String name, int age) {
        try {
            Thread.sleep(5000);
            return "hi, " + name + ", " + age;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
还是一个一个同步执行的。这样耗时是50*5000,使用异步调用应该是大大减小这个时间才对
如果我使用spring的@Async注解,又不能使用hessian接口,FutureTask不能被序列化,比较郁闷啊。

为什么啊要Sleep5秒钟呢?后台应该是用一个线程池来处理这些请求,对于单个请求是同步的,但是这一批请求应该是并发处理的。后台你用的是Missian的Server吗?有需要可以加我MSN,在线讨论一下,效率高些。gh_aiyz#hotmail.com
3 楼 yanwt 2010-12-15  
我不是这个意思,我是说我一次发了50个请求,如:
  for (int i = 0; i < 50; i++) {
            AsyncFuture<String> future = async.asyncHello(time + "gg", i, String.class);
            resultList.add(future);
            System.out.println("testasync:"+System.currentTimeMillis());
        }
后台HelloImpl中的
public String asyncHello(String name, int age) {
        try {
            Thread.sleep(5000);
            return "hi, " + name + ", " + age;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
还是一个一个同步执行的。这样耗时是50*5000,使用异步调用应该是大大减小这个时间才对
如果我使用spring的@Async注解,又不能使用hessian接口,FutureTask不能被序列化,比较郁闷啊。
2 楼 gh_aiyz 2010-12-15  
fs.get();这种方式是同步的,文档中已有说明,异步可以用以下方式:
1、用annotation标注回调类及回调方法
2、在客户端方法最后一个参数传入Callback对象
3、使用AsyncFuture.addLisnter();

fs.get()是同步的,这符合所有Future操作的原义。
1 楼 yanwt 2010-12-15  
刚试用了一下,感觉请求是异步发送的,但服务还是同步调用的,一个处理完了才会处理下一个。
测试代码如下:
HelloAsync async = (HelloAsync) asyncMissianProxyFactory.create(HelloAsync.class, "tcp://localhost:1235/hello");
        long time = System.currentTimeMillis();
        List<AsyncFuture<String>> resultList = new ArrayList<AsyncFuture<String>>();

        for (int i = 0; i < 50; i++) {
            AsyncFuture<String> future = async.asyncHello(time + "gg", i, String.class);
            resultList.add(future);
            System.out.println("testasync:"+System.currentTimeMillis());
        }
        for (AsyncFuture<String> fs : resultList) {
                System.out.println(fs.get());     //打印各个线程(任务)执行的结果
        }

相关推荐

    missian:一个java RPC框架,无模式风格

    1. **克隆源码**:使用Git工具克隆"missian-master"仓库到本地。 2. **构建项目**:通过Maven或Gradle等构建工具编译源代码。 3. **阅读文档**:查看项目文档以了解如何配置和服务调用。 4. **编写客户端和服务端**...

    Spring集成ActiveMQ配置

    6. **Missian ActiveMQ-JMS简单实例**:这可能是一个具体的项目实例,它展示了如何在Spring应用中使用ActiveMQ实现异步RPC(远程过程调用)。在这种模式下,一个服务通过消息将请求发送到队列,另一端的服务监听队列...

    YOLO算法-数据集数据集-330张图像带标签-椅子-书桌.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    java毕设项目之ssm蜀都天香酒楼的网站设计与实现+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    weixin138社区互助养老+ssm(论文+源码)-kaic.zip

    weixin138社区互助养老+ssm(论文+源码)_kaic.zip

    光纤到户及通信基础设施报装申请表.docx

    光纤到户及通信基础设施报装申请表.docx

    java毕设项目之ssm基于jsp的精品酒销售管理系统+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    功能完善的电商数据智能爬虫采集系统项目全套技术资料.zip

    功能完善的电商数据智能爬虫采集系统项目全套技术资料.zip

    YOLO算法-刀数据集-198张图像带标签-刀-枪.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    Android程序开发初级教程WORD文档doc格式最新版本

    ### Android程序开发初级教程(一):初识Android **平台概述** Google推出的Android操作系统平台已经正式亮相,这是一个基于Linux内核的开源操作系统。对于开发者而言,了解其架构和支持的开发语言至关重要。以下是Android平台的架构概览: **平台架构及功能** 1. **应用框架(Application Framework)**:包含可重用和可替换的组件,确保所有软件在该层面上的平等性。 2. **Dalvik虚拟机(Dalvik Virtual Machine)**:一个基于Linux的虚拟机,为Android应用提供运行环境。 3. **集成浏览器(Integrated Browser)**:基于开源WebKit引擎的浏览器,位于应用层。 4. **优化图形(Optimized Graphics)**:包括自定义的2D图形库和遵循OpenGL ES 1.0标准的3D实现。 5. **SQLite数据库**:用于数据存储。 6. **多媒体支持(Media Support)**:支持通用音频、视频以及多种图片格式(如MPEG4, H.264

    【组合数学答案】组合数学-苏大李凡长版-课后习题答案

    内容概要:本文档是《组合数学答案-网络流传版.pdf》的内容,主要包含了排列组合的基础知识以及一些经典的组合数学题目。这些题目涵盖了从排列数计算、二项式定理的应用到容斥原理的实际应用等方面。通过对这些题目的解析,帮助读者加深对组合数学概念和技巧的理解。 适用人群:适合初学者和有一定基础的学习者。 使用场景及目标:可以在学习组合数学课程时作为练习题参考,也可以在复习考试或准备竞赛时使用,目的是提高解决组合数学问题的能力。 其他说明:文档中的题目覆盖了组合数学的基本知识点,适合逐步深入学习。每个题目都有详细的解答步骤,有助于读者掌握解题思路和方法。

    .net core mvc在线考试系统asp.net考试系统源码考试管理系统 主要技术: 基于.net core mvc架构和sql server数据库,数据库访问采用EF core code fir

    .net core mvc在线考试系统asp.net考试系统源码考试管理系统 主要技术: 基于.net core mvc架构和sql server数据库,数据库访问采用EF core code first,前端采用vue.js和bootstrap。 功能模块: 系统包括前台和后台两个部分,分三种角色登录。 管理员登录后台,拥有科目管理,题库管理,考试管理,成绩管理,用户管理等功能。 教师登录后台,可进行题库管理,考试管理和成绩管理。 用户登录前台,可查看考试列表,参加考试,查看已考试的结果,修改密码等。 系统实现了国际化,支持中英两种语言。 源码打包: 包含全套源码,数据库文件,需求分析和代码说明文档。 运行环境: 运行需vs2019或者以上版本,sql server2012或者以上版本。

    YOLO算法-易拉罐识别数据集-512张图像带标签-可口可乐.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    (175415460)基于SpringBoot的通用管理系统源码+数据库+项目文档,前后端分离的通用管理系统模版,可用于开发毕业设计

    包含了登陆注册、用户管理、部门管理、文件管理、权限管理、日志管理、个人中心、数据字典和代码生成这九个功能模块 系统采用了基于角色的访问控制,角色和菜单关联,一个角色可以配置多个菜单权限;然后再将用户和角色关联,一位用户可以赋予多个角色。这样用户就可以根据角色拿到该有的菜单权限,更方便管理者进行权限管控。 本系统还封装了文件管理功能,在其他模块如若要实现图片/文件上传预览时,前端只需导入现成的 Vue 组件即可实现(使用 viewerjs 依赖实现),后端只需定义 String 类型的实体类变量即可,无需再去研究文件上传预览的相关功能,简化了开发者的工作量。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    三相10Kw光伏并网逆变器 包含全套理图 PCB 源代码

    三相10Kw光伏并网逆变器。包含全套理图 PCB 源代码

    GJB 5236-2004 军用软件质量度量

    GJB 5236-2004 军用软件质量度量文档,本称准规定了车用软件产品的质重模型和基本的度量。本标准为确定车用软件质量需求和衡量军用 软件产品的能力提供了一个框架。

    (179941432)基于MATLAB车牌识别系统【GUI含界面】.zip

    基于MATLAB车牌识别系统【GUI含界面】.zip。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    (9546452)宿舍管理系统

    【宿舍管理系统】是一种专为高校或住宿机构设计的信息化解决方案,旨在提高宿舍管理的效率和准确性。该系统包含了多项核心功能,如宿舍管理员管理、宿舍信息维护、查询、卫生检查以及电费缴纳等,旨在实现全面的宿舍运营自动化。 **宿舍管理员管理**功能允许指定的管理员进行用户权限分配和角色设定。这包括对管理员账户的创建、修改和删除,以及设置不同的操作权限,例如只读、编辑或管理员权限。通过这样的权限控制,可以确保数据的安全性和管理的规范性。 **宿舍添加与管理**是系统的基础模块。管理员可以录入宿舍的基本信息,如宿舍号、楼栋、楼层、房间类型(单人间、双人间等)、容纳人数、设施配置等。此外,系统还支持批量导入或导出宿舍信息,方便数据的备份和迁移。 **查询功能**是系统的重要组成部分,它允许管理员和学生根据不同的条件(如宿舍号、楼栋、学生姓名等)快速查找宿舍信息。此外,系统还可以生成各种统计报告,如宿舍占用率、空闲宿舍数量等,以便于决策者进行资源优化。 **卫生检查**功能则是对宿舍卫生状况进行定期评估。管理员可设定检查计划,包括检查周期、评分标准等,并记录每次检查的结果。系统能自动生成卫生报表,用于

    YOLO算法-包装好的服装数据集-654张图像带标签-.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    九缸星形发动机点火器3D

    九缸星形发动机点火器3D

Global site tag (gtag.js) - Google Analytics