AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

Java Remoting 远程服务(下)

  • 2012-02-02
  • 本文字数:3985 字

    阅读完需:约 13 分钟

上篇分别介绍了Java Remoting 远程服务中的RMI、EJB、Web Service 等技术,下篇继续分享其他的内容。

4. Hessian

Hessian( http://hessian.caucho.com ) 是一种轻量级的 Web Service, 采用的是二进制的 RPC 协议。

图五:Hessian 架构图 [5]

如图五所示,Hessian 可以形容是一种基于二进制协议提供 RMI 功能的组件。

接下来我们使用 Hessian 来实现本文的用例。

  1. 接口类 IAnimalService.java
复制代码
public interface IAnimalService {
public String getMonkeyName();
}
  1. 实现类 AnimalServiceImp.java
复制代码
public class AnimalServiceImp implements IAnimalService {
@Override
public String getMonkeyName() {
return "I'm Jacky";
}
}
  1. 服务端容器 Tomcat 配置 Web.xml(不需要单独编写 Servlet 代码)
复制代码
<servlet>
<servlet-name>AnimalService</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>com.demo.AnimalServiceImp</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>com.demo.IAnimalService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>AnimalService</servlet-name>
<url-pattern>/service/animalService</url-pattern>
</servlet-mapping>
</servlet>
  1. 客户端 Client.java
复制代码
final String url = "http://localhost:8080/service/animalService";
HessianProxyFactory factory = new HessianProxyFactory();
IAnimalService proxy = (IAnimalService) factory.create(IAnimalService.class, url);
System.out.println(proxy.getMonkeyName());

使用 Hessian 的利弊:

  • 优势:使用简单,速度快;跨语言,跨平台;可以用来兼容 legacy 系统的功能。
  • 劣势:安全性的支持不够强,不支持两阶段事务。

通过上面的例子我们可以看出,Hessian 使用起来非常简单简单,而且性能评测结果显示 Hessian 高于基于 XML 协议的 RPC 技术 ( http://daniel.gredler.net/2008/01/07/java-remoting-protocol-benchmarks/ )。笔者认为在局域网内 Hessian 取代 WebService 是可行的,谁愿意花时间去研究相对笨重的 Web Service 框架,而且运行相率又很一般呢。大家可能想问,Hessian 到底快在哪呢?有两点,首先 Hessian 采用的是二进制的 RPC 协议,其次 Hessian 的序列化速度也比 Java 本身序列化要快。因而选择 Hessian 作为解决方案的企业也越来越多。

5. NIO(Mina/Netty)

Java NIO 可以理解为我们常说的非阻塞 IO(异步 IO),这个概念在高并发、多线程的环境里面尤为适用。NIO 的基本原理是选择器来处理 IO 请求,将每个请求做标识,塞入处理队列;每个客户端请求进入睡眠,等待唤醒。

图六:异步 IO 工作原理 [6]

图六展示了异步 IO 的工作原理,很显然异步 IO 在高并发的情况下可以节省系统很多资源(对比阻塞 IO,异步 IO 不需要开启同等数量的服务线程)。

接下来我们使用异步 IO 来实现本文的用例,第三方库使用的是 Netty。

  1. 接口类 IAnimalService.java, Request.java ```

public interface IAnimalService extends Serializable {
public String getMoneyName();
}
public class Request implements Serializable {
/**
* 序列号
/
private static final long serialVersionUID = 3701941641993894303L;@SuppressWarnings(“rawtypes”)
private Class service; // 接口类
private String method; // 调用方法名称
private Object[] paras; // 调用方法参数
private String version; // 服务版本
/
*
* @return the service
/@SuppressWarnings(“rawtypes”)
public Class getService() {
return service;
}
/
*
* @param service the service to set
/
public void setService(Class service) {
this.service = service;
}
/
*
* @return the method
/
public String getMethod() {
return method;
}
/
*
* @param method the method to set
/
public void setMethod(String method) {
this.method = method;
}
/
*
* @return the paras
/
public Object[] getParas() {
return paras;
}
/
*
* @param paras the paras to set
/
public void setParas(Object[] paras) {
this.paras = paras;
}
/
*
* @return the version
/
public String getVersion() {
return version;
}
/
*
* @param version the version to set
*/
public void setVersion(String version) {
this.version = version;
}
}

复制代码
2. 实现类 AnimalServiceImp.java ```
public class AnimalServiceImp implements IAnimalService, Serializable {
/**
* 序列号
*/
private static final long serialVersionUID = -160535222600556362L;@Override
public String getMoneyName() {
return "I'am Jackey";
}
}
  1. 服务器端 Server.java ```

final int port = 9990;
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeLine = Channels.pipeline(new SimpleChannelUpstreamHandler() {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// 监听消息到达
Request obj = (request) e.getMessage();
if (obj.getService().equals(IAnimalService.class)) {
Method targetMethod = obj.getService().getMethod(obj.getMethod(), new Class[0]);
Object result = targetMethod.invoke(new AnimalServiceImp(), obj.getParas());
e.getChannel().write(result);
}
}
});
pipeLine.addFirst(“encoder”, new ObjectEncoder()); // 对象编码器
pipeLine.addFirst(“decoder”, new ObjectDecoder()); // 对象解码器
return pipeLine;
}
});
bootstrap.bind(new InetSocketAddress(port)); // 启动服务并绑定端口

复制代码
4. 客户端代码 Client.java ```
ClientBootstrap client = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.<i>newCachedThreadPool</i>(), Executors.<i>newCachedThreadPool</i>()));
client.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeLine = Channels.<i>pipeline</i>(new SimpleChannelUpstreamHandler() {
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// 创建连接发送请求
Request r = new Request();
r.setVersion("1.0.0"); // 设置版本
r.setService(IAnimalService.class); // 设置服务类型
r.setMethod("getMoneyName"); // 调用服务方法名称
r.setParas(null); // 参数
e.getChannel().write(r);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{
// 监听消息到达
System.<i>out</i>.println(e.getMessage().toString());
}
});
pipeLine.addFirst("encoder", new ObjectEncoder()); // 对象编码器
pipeLine.addFirst("decoder", new ObjectDecoder<u>()</u>); // 对象解码器
return pipeLine;
}
});
client.setOption("tcpNoDelay", true);
client.setOption("keepAlive", true);
ChannelFuture future = client.connect(new InetSocketAddress("127.0.0.1", 9990));
future.getChannel().getCloseFuture().awaitUninterruptibly();
client.releaseExternalResources(); // 释放外部资源

上述代码的实现稍有复杂,主要的结构是客户端将请求对象编码并发送管道,服务端将接受的字节流解码为对象,调用相应的方法并将结果返还至客户端。感兴趣的读者可以查看 Netty 官网 ( http://www.jboss.org/netty ) 来了解详情。

中国最大的互联网公司之一,淘宝,内部使用的服务框架 HSF 就采用了这种方式 (采用的第三方 NIO 库是 Mina) [7] 。笔者认为使用 NIO 这种方式来做分布式应用的优劣也是非常明显的:

  1. 优点:基于 TCP 通信,效率上高于 HTTP 的方式,非阻塞 IO 应对高并发绰绰有余。根据具体的需要制定数据传输的格式,可扩展性强。
  2. 缺点:不能跨语言,无法穿透防火墙。

结论

对企业来讲,Java Remoting 采取何种方案没有一个特定的标准。根据笔者的经验,业务特点以及数据吞吐量决定了技术的选择方向。比如第三方数据接口,重点考虑的是跨平台、跨语言、支持高并发、保证安全;而局域网内的分布式服务,重点考虑的是高性能、稳定性、可伸缩性。

引用

[5] http://safehammad.com/tag/hessian/

[6] http://onjava.com/onjava/2002/09/04/nio.html

[7] http://archive.cnblogs.com/a/1963077/

[8] http://www.salesforce.com/us/developer/docs/api/index.htm

作者

李湃,上海交通大学计算机硕士毕业,5 年互联网的行业经验,现就职于国内某互联网公司,喜欢开源技术,对于 Java 企业架构、分布式技术、高性能高可靠软件设计有极大的热情,希望能对国内社区有所贡献。博客地址: http://haperkelu2011.iteye.com/


感谢崔康对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2012-02-02 00:007717

评论

发布
暂无评论
发现更多内容

局域网IP扫描软件:IP Scanner Pro激活版

真大的脸盆

Mac IP 局域网管理 IP扫描工具 局域网扫描

软件测试/测试开发丨两个步骤轻松搞定测试环境问题

测试人

软件测试 自动化测试 测试开发

软件测试/测试开发丨通用 api 封装实战,带你深入理解 PO

测试人

软件测试 自动化测试 测试开发

不动产行业国产化加速,明源云上榜《中国信创500强》

科技热闻

从零学习SDK(2)SDK的基本概念和组成部分

MobTech袤博科技

Excelize 入选 2022 中国开源创新大赛优秀项目

xuri

golang 开源 Go 语言 Excelize OOXML

MobTech MobLink|无码邀请是怎么处理的

MobTech袤博科技

从逻辑到硬件:如何转换PCB布局?

华秋PCB

工具 电路 PCB PCB布局 PCB设计

2023Java岗面试,进互联网大厂必备Java面试八股文真题解析

程序知音

Java java面试 后端技术 八股文 Java面试八股文

恶意爬虫?能让恶意爬虫遁于无形的小Tips

宙哈哈

Python html nginx 爬虫

基于 Nginx&Lua 实现自建服务端埋点系统

亚马逊云科技 (Amazon Web Services)

Amazon

关于验证码,你不知道的一些问题!

宙哈哈

php html 记录 验证码

AntDB数据库携超融合流式实时数仓亮相第25届中国高速公路信息技术化大会

亚信AntDB数据库

AntDB AntDB数据库 企业号 4 月 PK 榜

【干货】验证码的常见类型总结

宙哈哈

php html 验证码 短信验证码

长安信托:拥抱数字信托,探索多项目管理新路径

万事ONES

Higress GitHub star 突破 1k,来自社区开发者和用户的寄语

阿里巴巴云原生

阿里云 云原生 Higress

AI开发实践:关于停车场中车辆识别与跟踪

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 4 月 PK 榜 车辆检测

联合解决方案|亚信科技AntDB携手蓝凌软件,助推企业数字化办公转型升级

亚信AntDB数据库

AntDB AntDB数据库 企业号 4 月 PK 榜

架构训练营模块二作业

请叫我馒头哥丶

架构实战营

GaussDB(DWS)云原生数仓技术解析

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

社区分享 | Orillusion 引擎入门系列 —— 如何创建一个简单的 3D 示例

Orillusion

WebGL 元宇宙 web3d #WebGPU #开源

建木在 Rainbond 上使用实践

北京好雨科技有限公司

云原生 CI/CD #Kubernetes# rainbond 企业号 4 月 PK 榜

喜讯!天翼云荣获国际AI顶会ABAW季军

天翼云开发者社区

最新版本 Stable Diffusion 开源 AI 绘画工具之使用篇

江户川码农

人工智能 图文生成 AI绘画 Stable Diffusion

Java Remoting远程服务(下)_Java_李湃_InfoQ精选文章