分布式编程技术的基本思想:客户计算机产生一个请求,然后将这个请求通过网络发送到服务器。服务器处理这个请求,并发送回一个针对该客户端的响应,供客户端进行分析。
客户端和服务端之间用代理进行通讯,客户端调用代理进行常规的方法调用,而客户端代理与服务端代理进行联系,服务端代理以常规方式调用服务器对象上的方法。
代理之间通信技术:
    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. yum报[Errno 256] No more mirrors to try

    解决方法: yum clean all            #清除yum缓存yum makecache      #将服务器软件包写到本地缓存,提高包的搜索.安装效率

  2. 监控之--Nagios如何监控本地主机及本地服务

    上一节内容介绍了Nagios监控服务在linux环境下的安装过程,本节内容将详细介绍如何使用已经安装的Nagios服务的一些配置文件的使用以及如何监控本地相关服务,如要完成对一台主机的监控Nagios ...

  3. 洛谷P3018 [USACO11MAR]树装饰Tree Decoration

    洛谷P3018 [USACO11MAR]树装饰Tree Decoration树形DP 因为要求最小,我们就贪心地用每个子树中的最小cost来支付就行了 #include <bits/stdc++ ...

  4. SaltStack数据系统之Grains、Pillar

    SaltStack数据系统之Grains.Pillar 1.什么是Grains? Grains是saltstack的组件,用于收集salt-minion在启动时候的信息,又称为静态信息.Grains是 ...

  5. Jaba_Web--JDBC 修改记录操作模板

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...

  6. unittest(简介)

    一.unittest框架介绍: unittest框架是python中的一个单元测试框架,该模块包括许多的类如 TestCase 类.TestSuite 类.TextTestRunner 类.TestR ...

  7. CC2530定时器的应用

    [例1]利用定时器计数实现5中彩灯的变化形式,基于模模式的.两个标志位,一个是定时器计数,一个是彩灯的状态. #include "ioCC2530.h" #define D3 P1 ...

  8. 教你配置windows上的windbg,linux上的lldb,打入clr内部这一篇就够了

    一:背景 1. 讲故事 前几天公众号里有位兄弟看了几篇文章之后,也准备用windbg试试看,结果这一配就花了好几天,(づ╥﹏╥)づ,我想也有很多跃跃欲试的朋友在配置的时候肯定会遇到这样和那样的问题,所 ...

  9. Linux编程实现递归查找文件

    命令格式如下:SCRIPT_NAME       SEARCH_ON_DIR       SEARCH_FILENAME #!/bin/bash Find(){ files=`` for file i ...

  10. STM32 标准库3.5修改默认外部8M晶振为16M晶振

    ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...