RMI(即Remote Method Invoke 远程方法调用)

  • 远程对象: 用于远程客户端调用 必需继承java.rmi.Remote,每个调用方法必须添加java.rmi.RemoteException异常

  • 远程对象实现:用于远程服务器,实现调用逻辑 必需继承UnicastRemoteObject

  • 远程服务器:通过LocateRegistry注册服务

  • 远程客户端:通过LocateRegistry查找服务,调用方法即可发送内容 Naming是LocateRegistry的辅助工具类

import java.rmi.Remote;
import java.rmi.RemoteException; public interface ITestRMIService extends Remote {
//必须加RemoteException否则运行出错: java.rmi.server.ExportException
public String a(String content) throws RemoteException; public TestRMIObj b(TestRMIObj input) throws RemoteException;
}
// UnicastRemoteObject用于导出的远程对象和获得与该远程对象通信的存根。否则运行出错:java.rmi.MarshalException
public class TestRMIServiceImpl extends UnicastRemoteObject implements ITestRMIService {
private static final long serialVersionUID = -6460154344452562895L; public TestRMIServiceImpl() throws RemoteException {
super();
} @Override
public String a(String content) {
System.out.println("call : a"+ content );
return "server >> " + content;
} @Override
public TestRMIObj b(TestRMIObj input) throws RemoteException {
System.out.println("call b : "+ input.getB().length );
input.setA(12);
return input;
}
}
//必须实现Serializable该对象要支持 Serializable
public class TestRMIObj implements Serializable { private static final long serialVersionUID = 2367853017282270281L;
private int a;
private Integer[] b; public int getA() {
return a;
} public Integer[] getB() {
return b;
} public void setA(int a) {
this.a = a;
} public static TestRMIObj of(int a, Integer... b) {
TestRMIObj ret = new TestRMIObj();
ret.a = a;
ret.b = b;
return ret;
}
}
public class ServerRMI {
public static void main(String[] args) {
try {
// 实例化实现了IService接口的远程服务ServiceImpl对象
ITestRMIService service02 = new TestRMIServiceImpl();
// 本地主机上的远程对象注册表Registry的实例,并指定端口为8888
LocateRegistry.createRegistry(8888);
// 把远程对象注册到RMI注册服务器上,并命名为service02
// 绑定的URL标准格式为:rmi://host:port/name
Naming.bind("rmi://localhost:8888/service02", service02);
} catch (Exception e) {
e.printStackTrace();
} System.out.println("服务器向命名表注册了1个远程服务对象!");
}
}
public class ClientRMI {
private ITestRMIService service; public void start() {
String url = "rmi://localhost:8888/";
try {
// 在RMI服务注册表中查找名称为service02的对象,并调用其上的方法
service = (ITestRMIService) Naming.lookup(url + "service02");
System.out.println(service.a("你好!"));
System.out.println(service.b(TestRMIObj.of(1, 2, 3, 4)).getA());
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
ClientRMI rmi = new ClientRMI();
rmi.start();
while (true) {
Thread.sleep(500);
rmi.service.a("a");
}
}
}

使用rmi开发网络通信非常简单,代码量比写model还少,开发者不需要考虑对象序列化,网络IO模型,粘包/半包、传输协议等问题

但它应用场景非常少,不适合大规模的应用,比较适合s/s服务间调用,原因是对象序列化数据量大,采用的是BIO模型

RMI与RPC有什么区别呢

RPC(Remote Procedure Call Protocol)远程过程调用协议

程序可使用这种协议向网络中的另一台计算机上的程序请求服务。由于使用 RPC 的程序不必了解支持通信的网络协议的情况,因此 RPC 提高了程序的互操作性。在 RPC 中,发出请求的程序是客户程序,而提供服务的程序是服务器

可以这样理解rmi是sun公司基于rpc制定的实现标准

[编织消息框架][消息服务]rmi的更多相关文章

  1. [编织消息框架][消息服务]jmx

    JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序.设备.系统等植入管理功能的框架,使用的是RMI技术. 比较经典的应用jdk bin目录下 jcons ...

  2. 「 从0到1学习微服务SpringCloud 」08 构建消息驱动微服务的框架 Spring Cloud Stream

    系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...

  3. [编织消息框架][netty源码分析]2 eventLoop

    eventLoop从命名上看是专门处理事件 事件系统主要由线程池同队列技术组成,有以下几个优点 1.任务出队有序执行,不会出现错乱,当然前提执行线程池只有一个 2.解偶系统复杂度,这是个经典的生产者/ ...

  4. 使用 Spring Cloud Stream 构建消息驱动微服务

    相关源码: spring cloud demo 微服务的目的: 松耦合 事件驱动的优势:高度解耦 Spring Cloud Stream 的几个概念 Spring Cloud Stream is a ...

  5. 消息驱动式微服务:Spring Cloud Stream & RabbitMQ

    1. 概述 在本文中,我们将向您介绍Spring Cloud Stream,这是一个用于构建消息驱动的微服务应用程序的框架,这些应用程序由一个常见的消息传递代理(如RabbitMQ.Apache Ka ...

  6. Spring Cloud Alibaba学习笔记(12) - 使用Spring Cloud Stream 构建消息驱动微服务

    什么是Spring Cloud Stream 一个用于构建消息驱动的微服务的框架 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互, ...

  7. 搭建websocket消息推送服务,必须要考虑的几个问题

    近年,不论是正在快速增长的直播,远程教育以及IM聊天场景,还是在常规企业级系统中用到的系统提醒,对websocket的需求越来越大,对websocket的要求也越来越高.从早期对websocket的应 ...

  8. 优化技术专题-线程间的高性能消息框架-深入浅出Disruptor的使用和原理

    前提概要 简单回顾 jdk 里的队列: 阻塞队列: ArrayBlockingQueue主要通过:数组(Object[])+ 计数器(count)+ ReetrantLock的Condition (n ...

  9. 异步tcp通信——APM.Server 消息推送服务的实现

    消息推送服务 服务器推送目前流行就是私信.发布/订阅等模式,基本上都是基于会话映射,消息对列等技术实现的:高性能.分布式可以如下解决:会话映射可采用redis cluster等技术实现,消息对列可使用 ...

随机推荐

  1. NTP时间同步 服务端 客户端 自动化安装配置

    NTP时间同步 服务端 客户端 自动化安装配置 原创内容 http://www.cnblogs.com/elvi/p/7657994.html #!/bin/sh #运行环境 centos6.cent ...

  2. ESLint 的正式使用感受

    介绍ESLint ESLint 是一个代码规范和错误检查工具,有以下几个特性 所有东西都是可以插拔的.你可以调用任意的rule api或者formatter api 去打包或者定义rule or fo ...

  3. 51Nod--1085背包问题

    1085 背包问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2--Wn(Wi为整 ...

  4. Centos下安装git的web服务器

    直接上代码 [Shell] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...

  5. php结合redis实现高并发下的抢购、秒杀功能 (转载)

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...

  6. python中csv文件的读取问题

    在python读取csv格式的文件时,使用csv.reader读取文件对象,出现了line contains NULL byte的错误,如下: reader = csv.reader(open(fil ...

  7. Pythonh中的zip()与*zip()函数详解

    前言 实验环境: Python 3.6: 示例代码地址:下载示例: 本文中元素是指列表.元组.字典等集合类数据类型中的下一级项目(可能是单个元素或嵌套列表). zip(*iterables)函数详解 ...

  8. Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗

    Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗 零.致谢 感谢BOSS直聘相对权威的招聘信息,使本人有了这次比较有意思的研究之旅. 由于爬虫持续爬取 www.zhipin.com 网 ...

  9. day3、Linux快捷键及vim命令快捷键

    Linux命令行快捷键 快捷键: tab键  自动补全路径 目录  名字,  自动不全命令 快捷键: ctrl +l(小写) 清屏 . ctrl +c 取消当前操作 快捷键: ctrl +d(小写) ...

  10. Azure ARM (19) 将传统的ASM VM迁移到ARM VM (2)

    <Windows Azure Platform 系列文章目录> 因为我们在上一节中: Azure ARM (18) 将传统的ASM VM迁移到ARM VM (1) 已经创建了Azure V ...