发表于: 2021-04-13 22:38:15

1 1195


今天完成的事情:
了解spring RMI  RPC   
spring clould中的 Feign  这些都和远程调用相关的知识

了解单机,集群,分布式概念



明天计划的事情:

继续学习RMI



遇到的问题:

又是新知识,慢慢来吧



收获:


        RPC 远程过程调用: RPC(Remote Procedure Call Protocol)远程过程调用协议,通过网络从远程计算机上请求调用某种服务。 RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。



Spring RMI

      RMI全称是Remote Method Invocation-远程方法调用,是纯Java的网络分布式应用系统的核心解决方案之一。Java RMI 支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。RMI全部的宗旨就是尽可能简化远程接口对象的使用。



我们知道远程过程调用(Remote Procedure Call, RPC)可以用于一个进程调用另一个进程(很可能在另一个远程主机上)中的过程,从而提供了过程的分布能力。Java 的 RMI 则在 RPC 的基础上向前又迈进了一步,即提供分布式对象间的通讯


      RMI(Remote Method Invocation)为远程方法调用,是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。(通俗的讲:A机器上面有一个class,通过远程调用,B机器调用这个class 中的方法。)


      这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。



RMI包含部分:
远程服务的接口定义
远程服务接口的具体实现
桩(Stub)和框架(Skeleton)文件
一个运行远程服务的服务器
一个RMI命名服务,它允许客户端去发现这个远程服务
类文件的提供者(一个HTTP或者FTP服务器)

一个需要这个远程服务的客户端程序



在Spring中实现RMI:
①在服务器端定义服务的接口,定义特定的类实现这些接口;
②在服务器端使用org.springframework.remoting.rmi.RmiServiceExporter类来注册服务;
③在客户端使用org.springframework.remoting.rmi.RmiProxyFactoryBean来实现远程服务的代理功能;

④在客户端定义访问与服务器端服务接口相同的类



RMI的使用局限?

      由于客户机和服务器都是使用Java编写的,二者平台兼容性的要求仅仅是双方都运行在版本兼容的Java虚拟机上。



RMI调用远程方法的参数和返回值

      当调用远程对象上的方法时,客户机除了可以将原始类型的数据作为参数一外,还可以将对象作为参数来传递,与之相对应的是返回值,可以返回原始类型或对象,这些都是通过Java的对象序列化(serialization)技术来实现的。(换而言之:参数或者返回值如果是对象的话必须实现Serializable接口




RMI应用程序的基本模型





Java  RMI


继承接口
/**
* 在Java中,只要一个类extendsjava.rmi.Remote接口,即可成为存在于服务器端的远程对象,
* 供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上
* 调用的接口。任何远程对象都必须直接或间接实现此接口。只有在远程接口
* (扩展 java.rmi.Remote 的接口)中指定的这些方法才可被远程调用。
*/
public interface HelloWorld extends Remote {
/**extendsRemote接口的类或者其他接口中的方法若是声明抛出了RemoteException异常,
   * 则表明该方法可被客户端远程访问调用。
*/
public String sayHelloToSomeBody(String someBodyName) throws RemoteException;
}



服务层:

/**注册远程对象,向客户端提供远程对象服务
* 远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称
* 但是,将远程对象注册到RMI Service之后,客户端就可以通过RMI Service请求
* 到该远程服务对象的stub了,利用stub代理就可以访问远程服务对象了
*/
public class HelloWorldServer {
public static void main(String args[]) {
try {
/* 生成stubskeleton,并返回stub代理引用 */
HelloWorld helloWorld = new HelloWorldServerImpl();
//加上此程序,就可以不要在控制台上开启RMI的注册程序,1099RMI服务监视的默认端口
LocateRegistry.createRegistry(8888);
// 如果配置在远程服务器,把地址换成你的ip
System.setProperty("java.rmi.server.hostname","127.0.0.1");
Naming.bind("rmi://localhost:8888/Hello", helloWorld);
System.out.println(">>>>>INFO:远程IHello对象绑定成功!");
} catch (RemoteException e) {
System.out.println("创建远程对象发生异常!");
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println("发生重复绑定对象异常!");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("发生URL畸形异常!");
e.printStackTrace();
}
}



实现类:

/**
* 远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,
* 该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为存根
* 而服务器端本身已存在的远程对象则称之为骨架。其实此时的存根是客户端的一个代理,用于与服务器端的通信,
* 而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
*/
// java.rmi.server.UnicastRemoteObject构造函数中将生成stubskeleton
public class HelloWorldServerImpl extends UnicastRemoteObject implements HelloWorld {
// 这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常
public HelloWorldServerImpl () throws RemoteException {
super();
}
@Override
public String sayHelloToSomeBody(String someBodyName) throws RemoteException {
System.out.println("你好啊");
return someBodyName+"这是传入的参数";
}
}



SpringRMIClient:

public class SpringRMIClient {
public static void main(String args[]) {
try {
// 填写服务器ip
HelloWorld helloWorld = (HelloWorld) Naming.lookup("rmi://127.0.0.1:8888/Hello");
System.out.println(helloWorld.sayHelloToSomeBody("你好,世界!"));
} catch (NotBoundException e) {
} catch (MalformedURLException e) {
e.printStackTrace();
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}



先创建连接:



然后传入参数:



返回列表 返回列表
评论

    分享到