Java——分布式
客户端和服务端之间用代理进行通讯,客户端调用代理进行常规的方法调用,而客户端代理与服务端代理进行联系,服务端代理以常规方式调用服务器对象上的方法。
1.RMI,Java的远程方法调用技术,支持Java的分布式对象之间的方法调用。
2.CORBA,通过对象请求代理架构,支持任何编程语言编写的对象之间的方法调用。CORBA使用Internet Inter-ORB协议(IIOP)支持对象间通信。
3.Web服务架构是一个协议集,有时统一描述为WS-*。独立于编程语言,使用基于XML的通信格式。用于传输对象的格式则是简单对象访问协议(SOAP)。
若互相通信的程序都是由Java实现的,那么CORBA与WS-*的通用性和复杂性统统是不需要的。远程方法调用(RMI)专门针对Java应用之间的通信。
当客户代码要在远程对象上调用一个远程方法时,实际上调用的是代理对象上的一个普通方法,此代理对象称为存根(stub)。
存根位于客户端机器上,而非服务器上,它知道如何通过网络与服务器联系。存根将远程方法所需的参数打包成一组字节。队参数编码的过程叫参数编组,参数编组的目的的将参数转换成适合在虚拟机之间进行传递的格式。在RMI协议中,对象是使用序列化机制来进行编码的,在SOAP协议中,对象被编码为XML。
客户端的存根方法构造一个信息块,由以下部分组成:
被使用的远程对象的标识符;
被调用的方法的描述;
编组后的参数。
然后存根将此消息发送给服务器。服务器接收对象执行以下动作:
定位要调用的远程对象;
调用所需的方法,并传递客户端提供的参数;
捕获返回值或该调用参生的异常;
将返回值编组,打包返回给客户端存根。
客户端存根对来自服务器端的返回值或异常进行反编组,就成为了调用存根的返回值。
import java.rmi.Remote;
import java.rmi.RemoteException; /**
* 简单仓库的远程借口
* 远程对象的借口必须扩展Remote接口。接口中的所有方法必须声明抛出RemoteException异常,因为远程调用总是存在失败的可能。
*/
public interface Warehouse extends Remote {
double getPrice(String description) throws RemoteException;
}
实现接口
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map; /**
* 实现简单仓库远程借口的类
*该类是远程方法调用的目标。继承UnicastRemoteObject,这个类的构造器可以让它的对象供远程访问。
*有时候不继承UnicastRemoteObject,在这种情况下需手动初始化远程对象,并将它们传给静态的exportObject方法。在远程对象的构造器中调用exportObject方法:UnicastRemoteObjcet.exportObject(this,0);
*/
public class WarehouseImpl extends UnicastRemoteObject implements Warehouse {
private Map<String,Double> prices; public WarehouseImpl() throws RemoteException{
prices = new HashMap<String,Double>();
prices.put("Blackwell Toaster",24.95);
prices.put("ZapXpress Microwave", 49.95);
} public double getPrice(String description) throws RemoteException {
Double price = prices.get(description);
return price == null ? 0 : price;
} }
构造并注册WarehouseImpl对象
import java.rmi.RemoteException; import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* 第一个远程对象总要通过某种方式进行定位,JDK提供了自举注册服务。
* 服务器程序使用自举注册服务来注册至少一个远程对象,要注册一个远程对象,需要一个RMI URL和一个对实现对象的引用。
* RMI的URL以rmi:开头,后接服务器以及一个可选的端口号,接着是远程对象的名字。例如:rmi://regserver.mycompany.com:99/central_warehouse
* 默认情况下,主机名是localhost,端口为1099。服务器告诉注册表在给定位置将该对象关联或“绑定”到这个名字。
* 下面代码将一个WarehouseImpl对象注册到了同一个服务器上的RMI注册表中:
WarehouseImpl centralWarehouse = new WarehouseImpl();
Context namingContext = new InitialContext();
namingContext.bind("rmi:central_warehouse", centralWarehouse);
*
*/
public class WarehouseServer {
public static void main(String[] args) throws RemoteException,NamingException{
System.out.println("Constructing server implementation...");
WarehouseImpl centralWarehouse = new WarehouseImpl(); System.out.println("Binding server implementation to registry...");
Context namingContext = new InitialContext();
namingContext.bind("rmi:central_warehouse", centralWarehouse); System.out.println("Waiting for invocations from clients...");
}
}
客户端获得远程对象
import java.rmi.RemoteException;
import java.util.Enumeration; import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingException; public class WarehouseClient {
public static void main(String[] args) throws NamingException,RemoteException {
Context namingContext = new InitialContext(); System.out.println("RMI registry bindings:");
//通过下面的调用枚举所有注册过的RMI对象
//NameClassPair是一个助手类,它包含绑定对象的名字和该对象所属类的名字
Enumeration<NameClassPair> e = namingContext.list("rmi://localhost/");
while(e.hasMoreElements()) {
System.out.println(e.nextElement().getName());//打印注册对象的名字
}
//客户端通过下面方式来指定服务器和远程对象的名字,以此获得访问远程对象所需的存根
String url = "rmi://localhost/central_warehouse";;
Warehouse centralWarehouse = (Warehouse)namingContext.lookup(url); String descr = "Blackwell Toaster";
double price = centralWarehouse.getPrice(descr);
System.out.println(descr+":"+price);
}
}
部署RMI简单实例
创建两个目录分别用于启动服务器和客户端的类
server/
WarehouseServer.class
Warehouse.class
WarehouseImpl.class
client/
WarehouseClient.class
Warehouse.class
部署RMI应用时,通常需要动态地将类交付为运行程序,其中一个例子就是RMI注册表。注册表的一个实例要服务许多不同的RMI应用。当注册表启动时,无法预测将来会参生的所有注册表请求。RMI注册表会动态地加载之前从未遇到过的所有远程接口的类文件。
动态交付的类文件是通过标准的Web服务器发布的,服务器程序需使Warehouse.class文件对于RMI注册表来说是可获得的,所以将该文件放到第三个目录download中:
download/
Warehouse.class
部署应用,服务器、RMI注册表、Web服务器和客户端可以定位到四台不同的机器上。(由于一台机器部署测试例子没看懂,所以具体一台机器测试没做笔记)
扩展
javax.naming.InitialContext
InitialContext() 构建一个命名上下文,用来访问RMI注册表。
javax.naming.Context
static Object lookup(String name) 返回给定名字的对象。如果该名字尚未绑定则抛出NamingException异常。
static void bind(String name,Object obj) 将name和obj对象绑定。如果该对象已经绑定则抛出NameAlreadyBoundException异常。
static void unbind(String name) 解除该名字的绑定。解除一个不存在的绑定是合法的。
static void rebind(String name,Object obj) 将name和obj对象绑定。替换掉以前的绑定。
NamingEnumeration<NameClassPair> list(String name) 返回一个枚举列表,列出所有匹配的绑定对象。使用“rmi:”调用该方法可以列出所有MRI对象。
javax.naming.NameClassPair
String getName() 获取已命名对象的名字。
String getClassName() 获取已命名对象所属的类名。
java.rmi.Naming
static Remote lookup(String url) 返回URL对应的远程对象。如果该名字尚未绑定,抛NotBoundException异常。
static void bind(String name,Remote obj) 将name和远程对象obj绑定。如果该对象已经绑定抛AlreadyBoundException异常。
static void unbind(String name) 解除该名字的绑定。如果该名字没有绑定抛NotBound异常。
static void rebind(String name,Remote obj) 将name和远程对象obj绑定。替换掉以前的绑定。
static String[] list(String url) 参数url指定了某个注册表,返回注册表中的所有URL组成的字符串数组。
Java——分布式的更多相关文章
- Java分布式开发
分布式概念的引入是基于性能的提升,应用的可靠性而提出的.所谓Java分布式,即是在使用Java语言进行企业级应用开发的过程中,采用分布式技术解决业务逻辑的高并发.高可用性的一些架构设计方案. 1. R ...
- 5个强大的Java分布式缓存框架推荐
在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的 缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了 ...
- Java分布式处理技术(RMI,JDNI)
http://hedaoyuan.blog.51cto.com/4639772/813702 1.1 RMI的基本概念 1.1.1 什么是RMI RMI(Remote Method Invocatio ...
- Java分布式缓存框架
http://developer.51cto.com/art/201411/457423.htm 在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓 ...
- Java分布式锁之数据库实现
之前的文章<Java分布式锁实现>中列举了分布式锁的3种实现方式,分别是基于数据库实现,基于缓存实现和基于zookeeper实现.三种实现方式各有可取之处,本篇文章就详细讲解一下Java分 ...
- 学Java分布式和高架构,必懂的两大知识点!
今天小编为你们分享阿里巴巴2018年招聘应届毕业生,Java工程师的面试考题,主要分为三种 Java中获取 mysql连接的方式: 第一部分:分布式 三步变成:分布式 1.将你的整个软件视为一个系 ...
- 深入浅出Java分布式系统通信
对java分布式系统通信的理解: 1.集群模式,将相同应用模块部署多份 2.业务拆分模式,将业务拆分成多个模块,并分别部署 3.存储分布式 由于分布式概念太大,我们可以缩小下讨论的范围. 以下分布式的 ...
- JAVA分布式优惠券系统后台 手把手实战开发(买的,完整)
扫码关注,回复 “java分布式优惠券”,免费领取.本资源是本人花几十块买的,完整.
- java 分布式与集群的区别和联系(转)
本文主要介绍了java分布式与集群的区别和联系,具有很好的参考价值,下面跟着小编一起来看下吧 一.先说区别: 一句话:分布式是并联工作的,集群是串联工作的. 1.分布式是指将不同的业务分布在不同的地方 ...
- 5个强大的Java分布式缓存框架
在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了5 ...
随机推荐
- php数组存在重复的相反元素,去重复
$arr1=array('a_b','c_d','b_a','d_c'); $arr2=array('a_b','c_d','b_a','d_c'); 条件: a_b==b_a:c_d==d_c: 需 ...
- Cisco 交换机启用netflow
Router2951#configure terminal //Creating Flow Record router2951(config)# flow record NTArecord route ...
- .NET Core+WebApi+EF访问数据新增用户数据
新建一个.NET Core项目,我使用的IDE是VS2019 依次创建三个Core类库:第一个命名api.Model,第二个api.Common,第三个api.Bo 解释一下这个三类库的作用: 第一个 ...
- 使用PHP-Beast加密你的PHP源代码
PHP-Beast是一个PHP源码加密的模块,其使用DES算法加密,用户可以自定义加密的key来加密源代码. 1. PHP-Beast的安装 $ wget https://github.com/lie ...
- 图论--SCC缩点--Tarjan
// Tarjan算法求有向图强连通分量并缩点 /*强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作.*/ #include< ...
- python(while 循环语句)
一.循环语句 1.while 循环 当我们在 python 中需要重复执行一些动作的时候,这时我们就要用到循环 while 循环的结构,当条件成立的时候,就会执行里面的代码 while 循环不断的运行 ...
- 课堂管理系统;在线教辅平台;java课设
# 白泽智慧教辅平台 **说明:** 运行时需要修改位置: bzedu\src\main\resources\application.properties bzedu\src\main\resourc ...
- Docker配置TLS认证,修复因暴露2375端口引发漏洞
1.环境准备 # 查看Docker服务器主机名hostnamectl 这里记住我的主机名s130就好 # 静态主机名修改vi /etc/hostname# 临时主机名修改(重启失效)hostname ...
- Spring Framework 之AOP
Spring Framework 之AOP 目录 Spring Framework 之AOP 问题 AOP概述 AOP知识 1.连接点(Joinpoint) 2.切点(PointCut) 3.增强(A ...
- search(9)- elastic4s logback-appender
前面写了个cassandra-appender,一个基于cassandra的logback插件.正是cassandra的分布式数据库属性才合适作为akka-cluster-sharding分布式应用的 ...