分布式编程技术的基本思想:客户计算机产生一个请求,然后将这个请求通过网络发送到服务器。服务器处理这个请求,并发送回一个针对该客户端的响应,供客户端进行分析。
客户端和服务端之间用代理进行通讯,客户端调用代理进行常规的方法调用,而客户端代理与服务端代理进行联系,服务端代理以常规方式调用服务器对象上的方法。
代理之间通信技术:
    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。
    客户端的存根方法构造一个信息块,由以下部分组成:
        被使用的远程对象的标识符;
        被调用的方法的描述;
        编组后的参数。
    然后存根将此消息发送给服务器。服务器接收对象执行以下动作:
        定位要调用的远程对象;
        调用所需的方法,并传递客户端提供的参数;
        捕获返回值或该调用参生的异常;
        将返回值编组,打包返回给客户端存根。
    客户端存根对来自服务器端的返回值或异常进行反编组,就成为了调用存根的返回值。
   
RMI编程模型简单实例
    接口
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——分布式的更多相关文章

  1. Java分布式开发

    分布式概念的引入是基于性能的提升,应用的可靠性而提出的.所谓Java分布式,即是在使用Java语言进行企业级应用开发的过程中,采用分布式技术解决业务逻辑的高并发.高可用性的一些架构设计方案. 1. R ...

  2. 5个强大的Java分布式缓存框架推荐

    在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的 缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了 ...

  3. Java分布式处理技术(RMI,JDNI)

    http://hedaoyuan.blog.51cto.com/4639772/813702 1.1 RMI的基本概念 1.1.1 什么是RMI RMI(Remote Method Invocatio ...

  4. Java分布式缓存框架

    http://developer.51cto.com/art/201411/457423.htm 在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓 ...

  5. Java分布式锁之数据库实现

    之前的文章<Java分布式锁实现>中列举了分布式锁的3种实现方式,分别是基于数据库实现,基于缓存实现和基于zookeeper实现.三种实现方式各有可取之处,本篇文章就详细讲解一下Java分 ...

  6. 学Java分布式和高架构,必懂的两大知识点!

    今天小编为你们分享阿里巴巴2018年招聘应届毕业生,Java工程师的面试考题,主要分为三种 Java中获取 mysql连接的方式: 第一部分:分布式   三步变成:分布式 1.将你的整个软件视为一个系 ...

  7. 深入浅出Java分布式系统通信

    对java分布式系统通信的理解: 1.集群模式,将相同应用模块部署多份 2.业务拆分模式,将业务拆分成多个模块,并分别部署 3.存储分布式 由于分布式概念太大,我们可以缩小下讨论的范围. 以下分布式的 ...

  8. JAVA分布式优惠券系统后台 手把手实战开发(买的,完整)

    扫码关注,回复 “java分布式优惠券”,免费领取.本资源是本人花几十块买的,完整.

  9. java 分布式与集群的区别和联系(转)

    本文主要介绍了java分布式与集群的区别和联系,具有很好的参考价值,下面跟着小编一起来看下吧 一.先说区别: 一句话:分布式是并联工作的,集群是串联工作的. 1.分布式是指将不同的业务分布在不同的地方 ...

  10. 5个强大的Java分布式缓存框架

    在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了5 ...

随机推荐

  1. 3DMAX导出到Unity坐标轴转换问题

      这是我在3dmax中创建的1cm*1cm*1cm的立方体,右图为3dmax中的坐标系 当我们把这个立方体导入到unity中发现x轴意外的扭转了90度 为了解决这个问题,你需要对模型做出修正 1.选 ...

  2. H5 -- 取消a标签在点击时的背景颜色

    原文链接:点我 1.取消a标签在移动端点击时的蓝色 a { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); -webkit-user-sele ...

  3. CF--思维练习--CodeForces - 216C - Hiring Staff (思维+模拟)

    ACM思维题训练集合 A new Berland businessman Vitaly is going to open a household appliances' store. All he's ...

  4. CF1328B K-th Beautiful String

    CF1328B K-th Beautiful String,然而CF今天却上不去了,这是洛谷的链接 题意 一个长度为\(n\)的字符串,有2个\(\texttt{b}\)和\(n-2\)个\(\tex ...

  5. 配置中心Apollo搭建全过程

    总体架构 用户在Portal操作配置发布 Portal调用Admin Service的接口操作发布 Admin Service发布配置后,发送ReleaseMessage给各个Config Servi ...

  6. 从0开始学自定义View -1

    PS:好久没有写博客了,之前的东西有所忘记,百度一下竟然查到了自己的写过的博客,访问量还可以,一开始的写博客的初衷是把自己不会的记录下来,现在没想到也有博友会关注我,这就给了我动力,工作之余把零零碎碎 ...

  7. Hadoop入门学习笔记-第二天 (HDFS:NodeName高可用集群配置)

    说明:hdfs:nn单点故障,压力过大,内存受限,扩展受阻.hdfs ha :主备切换方式解决单点故障hdfs Federation联邦:解决鸭梨过大.支持水平扩展,每个nn分管一部分目录,所有nn共 ...

  8. Northwestern European Regional Contest 2014 Gym - 101482

    Gym 101482C Cent Savings 简单的dp #include<bits/stdc++.h> #define inf 0x3f3f3f3f #define inf64 0x ...

  9. JavaScript 浅析数组对象与类数组对象

    数组(Array对象) 数组的操作 创建数组方法 添加与修改数组元素 删除数组元素 使用数组元素 遍历数组元素 多维数组 数组相关的函数 concat() join() pop() push() sh ...

  10. C# 数据操作系列 - 0. 序言

    0. 前言 在上一个系列中,我们初步浏览了一下C#的基础知识.这句话的意思就是C#基础知识系列完结了,撒花.当然,并不是因为C#已经讲完了.正是因为我们轻轻地叩开了那扇门,才能看到门后面那瑰丽的世界. ...