架构设计(二)系统间通信管理
来源:互联网 发布:js split("") 编辑:程序博客网 时间:2024/06/06 02:19
系统间通信管理
一、基于消息方式实现系统间通信
1. Java自身技术: TCP/IP + BIO、TCP/IP + NIO、UDP/IP + BIO、 UDP/IP + NIO
- 开源项目: mina
二、 基于远程调用方式实现系统间通信
1. java自身技术: RMI 和 WebService
- 开源项目: Spring rmi 和 cxf
具体如下:
一、RMI
1、 rmi定义:
RMI(Remote Method Invocation, 远程方法调用),是jdk1.1中提供的JVM与JVM之间进行对象方法调用的技术框架的实现。通过RMI技术,某一个本地的JVM可以调用存在于另外一个JVM中的对象方法,就好像它仅仅是在调用本地JVM中的某个对象方法一样。JDK1.5版本中的RMI又进行了改进
2、 使用场景:
1). RMI是基于Java语言的,也就是说在RMI技术框架的描述中,只有server端和client端都使用java语言,才能使用RMI技术
2). RMI使用于两个系统都主要使用java语言进行构造,不需要考虑语言支持的情况,并且对两个java系统的通讯速度有要求的情况。
3). RMI是一个良好的、特殊的RPC实现:使用JRMP协议承载数据的描述,可以使用BIO和NIO两种IO通信模型,RMI框架可以在大规模集群系统中使用。
3、 框架的基本组成:
a. 定义RMI Remote接口
b. 实现这个RMI Remote接口
c. 生成Stub(桩)和Skeleton(骨架),这一步的具体操作视不同的JDK版本而有所不同(例如JDK1.5以后,Skeleton不需要手动)
d. 向”RMI注册表”注册在b步实现的RMI remote接口
e. 创建一个Remote客户端,通过java”命名服务”,在”RMI 注册表”所在的Ip Port中寻找注册好的RMI服务
f. Remote客户端像调用存在于本地JVM中对象那样,调用存在于远程JVM上的RMI接口
注意:
1). UnicastRemoteObject:代表RMI Server真实的服务提供者 将工作在 “本地JVM”上
2). Activatable: 代表RMI Server真实的服务提供者,不在 “本地JVM”上,而是通过”RMI Remote Server激活”技术,被序列化到”远程JVM”(即远程RMI注册表所在的JVM),并适时的被”远程JVM”加载运行
3). 两种JVM: RMI Server真实服务的JVM 和 RMI 注册表的JVM
4). Naming.rebind和Naming.bind区别: 前者如果注册表中已经有了这个服务,则之前的将被替换;而后者则抛出错误
5). registry.rebind和Naming.rebind区别: 前者是使用RMI注册表绑定,所以不需要写完整的RMI URL了;而后者是通过java的名称服务进行绑定,由于名称服务不止为RMI框架提供查询服务,所以在绑定时要书写完整的RMI URL。
4、 手动生成Stub类
rmic -classpath [项目class路径] [实现类]如: rmic -classpath E:\test\netty_frame com.rmi.RemoteServerImplrmiregistry 1099: 启动注册表JVM,需要将生成的stub文件和服务的接口文件放在classpath目录下面export CLASSPATH=$CLASSPATH:/home/test
5、 rmi框架总共有两种模式: UnicastRemoteObject和Activatable
6、 实现框架: spring rmi
7、 实例代码
// RemoteServerInterfacepublic interface RemoteServerInterface extends Remote{ /* * RMI接口 负责查询目前已经注册的所有用户进程 */ public List<UserInfo> queryAllUserInfo(String str) throws RemoteException; public List<UserInfo> queryAllUserInfo2(String str) throws RemoteException;}// RemoteServerImplpublic class RemoteServerImpl extends UnicastRemoteObject implements RemoteServerInterface { /* * 父类抛出异常,必须显示继承 */ public RemoteServerImpl() throws RemoteException { super(); } /** * */ private static final long serialVersionUID = -9099045958340509746L; @Override public List<UserInfo> queryAllUserInfo(String str) throws RemoteException { System.out.println("str"); List<UserInfo> users = new ArrayList<UserInfo>(); UserInfo user1 = new UserInfo(0, "zhangsan"); UserInfo user2 = new UserInfo(1, "lisi"); users.add(user1); users.add(user2); return users; } @Override public List<UserInfo> queryAllUserInfo2(String str) throws RemoteException { System.out.println("str"); List<UserInfo> users = new ArrayList<UserInfo>(); UserInfo user1 = new UserInfo(2, "zhangsan2"); UserInfo user2 = new UserInfo(3, "lisi2"); users.add(user1); users.add(user2); return users; }}// UserInfopublic class UserInfo implements Serializable { /** * */ private static final long serialVersionUID = -3413210243305788156L; private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public UserInfo(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "UserInfo [id=" + id + ", name=" + name + "]"; }}// RemoteUnicastMainpublic class RemoteUnicastMain { public static void main(String[] args) throws RemoteException { // 目前得出结论: 注册表jvm和RMI Server JVM 必须在同一台机器上,跨机器好像不行 Registry registry2 = LocateRegistry.getRegistry("10.0.228.111", 9527); Registry registry = LocateRegistry.createRegistry(9527); RemoteServerImpl serverImpl = new RemoteServerImpl(); registry.rebind("queryAllUserInfo", serverImpl); }}// RemoteClientpublic class RemoteClient { public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException { RemoteServerInterface remoteServerInterface = (RemoteServerInterface)Naming.lookup("rmi://127.0.0.1:9527/queryAllUserInfo"); List<UserInfo> queryAllUserInfo = remoteServerInterface.queryAllUserInfo("fuck"); for ( UserInfo user : queryAllUserInfo) { System.out.println(user.toString()); } System.out.println("-----------------------------------------"); List<UserInfo> queryAllUserInfo2 = remoteServerInterface.queryAllUserInfo2("fuck"); for ( UserInfo user : queryAllUserInfo2) { System.out.println(user.toString()); } }}// 以下这个是个人在理解的基础上所写的一个简单的例子public class Test1 { public static void main(String[] args) { Test1 t1 = new Test1(); // 服务端: 将接口实现类传递给注册表 Test2 t2 = new Test2(t1); System.out.println(t2.m1("fuck")); } public String m1(String str) { System.out.println(str); return str + "_return"; }}// 相当于 接口的实现类的stubclass Test2 extends Test1 { private Test1 t1; public Test2(Test1 t1) { this.t1 = t1; } @Override public String m1(String str) { try { Method m1 = Test1.class.getMethod("m1", String.class); return (String)m1.invoke(t1, str); } catch (NoSuchMethodException | SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } return null; }}
二、 WebService
1、 定义:
WebService是一种跨语言的系统间交互标准。在这个标准中,对外提供功能的一方以http的方式提供服务,该服务采用WSDL(Web Service Description Language)描述,在这个文件中描述服务所使用的协议、所期望的参数、返回的参数格式等,调用端和服务端通过SOAP(Simple Object Access Protocol)协议来进行交互
2、 使用说明:
在java中使用WebService须首先将服务器端的服务根据描述生成相应的WSDL文件,并将应用及此WSDL文件放入http服务器中,借助java辅助工具根据WSDL文件生成客户端stub代码。此代码的作用是将产生的对象请求信息封装为标准的SOAP格式数据,并发送请求到服务器,服务器端在接收到SOAP格式数据时进行转换,反射调用相应的java类
3、 实例代码:
服务器端通过@WebService来标记对外暴露的WebService实现类,通过调用Endpoint.publish将此Webservice实现发布到指定的http地址上。
客户端通过wsimport来访问相应地址的WSDL文件,从而生成调用服务器端的辅助类,应用即可通过调用此类来实现远程调用了
注意:
1). WebService传输的数据协议采用SOAP, SOAP对于复杂的对象结构比较难支持,其好处是能够支持跨语言
2). 无论是采用RMI还是WebService,都封装了网络通信的细节,使用起来会比较简单,但如果想对通信细节做一些调优或控制,也会比较麻烦
4、 实现框架: cxf
// Businesspublic interface Business { public String echo(String message);}// BusinessImplimport javax.jws.WebService;import javax.jws.soap.SOAPBinding;import javax.jws.soap.SOAPBinding.Style;import com.webservice.Business;@WebService(name="Business", serviceName="BusinessService", targetNamespace="http://WebService.chapter1.book/client")@SOAPBinding(style=Style.RPC)public class BusinessImpl implements Business { @Override public String echo(String message) { if ("quit".equalsIgnoreCase(message)) { System.out.println("Service will be shutdown"); System.exit(0); } System.out.println("Message from client: " + message); return "Server response: " + message; }}// BusinessMainpublic class BusinessMain { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:9527/BusinessService", new BusinessImpl()); System.out.println("Server has been started"); }}// 之后通过jdk的wsimport生成对应的stub// wsimport -keep http://127.0.0.1:9527/BusinessService?wsdl// 将生成的文件导入到项目中// BusinessClientpublic class BusinessClient { public static void main(String[] args) { BusinessService businessService = new BusinessService(); Business businessPort = businessService.getBusinessPort(); System.out.println(businessPort.echo("fuck you ")); }}
- 架构设计(二)系统间通信管理
- 架构设计:系统间通信(8)——通信管理与RMI 上篇
- 架构设计:系统间通信(9)——通信管理与RMI 下篇
- 架构设计:系统间通信(8)——通信管理与RMI 上篇
- 架构设计:系统间通信(9)——通信管理与RMI 下篇
- 系统架构设计(二)
- 架构设计:系统间通信(3)——IO通信模型和JAVA实践 上篇
- 架构设计:系统间通信(4)——IO通信模型和JAVA实践 中篇
- 架构设计:系统间通信(5)——IO通信模型和JAVA实践 下篇
- 架构设计:系统间通信(6)——IO通信模型和Netty 上篇
- 架构设计:系统间通信(7)——IO通信模型和Netty 下篇
- 架构设计:系统间通信(3)——IO通信模型和JAVA实践 上篇
- 架构设计:系统间通信(4)——IO通信模型和JAVA实践 中篇
- 架构设计:系统间通信(3)——IO通信模型和JAVA实践 上篇
- 架构设计:系统间通信(4)——IO通信模型和JAVA实践 中篇
- 架构设计:系统间通信(5)——IO通信模型和JAVA实践 下篇
- 架构设计:系统间通信(6)——IO通信模型和Netty 上篇
- 架构设计:系统间通信(7)——IO通信模型和Netty 下篇
- 使用Cookie的B2C的电商系统购物车的业务逻辑
- 笔试
- A Brief Intro to Daily Scrum
- JetBrains IDE Support 调试工具(页面自动刷新)
- Mysql存储过程------存储过程的基本概念和基本使用方法
- 架构设计(二)系统间通信管理
- 数据结构基础入门(一)
- 《快彩网》彩票php源码 使用thinkphp框架开发
- 如何优化你网站的全名
- android 6.0 动态权限处理
- 面试题记录
- 第二十七篇 导航栏和内容块
- 明星主页页面制作
- 分油问题