java实现简单的RPC

RPC解析

什么是RPC呢?RPC(Remote Procedure Call)是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。分布式系统各个几点之间通信通常只能依靠网络,因此RPC机制广泛的应用在分布式系统当中,典型的一个场景就是主从分布式架构系统中的主节点给工作节点部署任务。本文将通过一个的简单的例子讲解RPC的执行过程。

RPC涉及到Java网络通信,反射机制,代理模式(动态代理技术)。考虑到同学们可能对上述技术并不了解因此本文先简单介绍上述技术点,然后再通过例子讲解RPC的工作过程。

如果同学们已经了解相关技术可以直接跳至最后一节。

JavaSocket

Java网络通信技术请见前文JavaSocket

反射机制

Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种 动态的获取信息 以及 动态调用对象的方法 的功能称为 Java 的反射机制

反射机制很重要的一点就是“运行时”,其使得我们可以在程序运行时加载、探索以及使用编译期间完全未知的 .class 文件。换句话说,Java 程序可以加载一个运行时才得知名称的 .class 文件,然后获悉其完整构造,并生成其对象实体、或对其 fields(变量)设值、或调用其 methods(方法)

我们用它可以做什么事呢?

  • 运行时生成实例并调用其某方法

  • 在类没有设置set方法时,修改类某实例的私有成员变量

  • 客户端向服务端传递类信息

  • 等等

获取类信息的三种方法:(Object表示任意类,object表示任意类的实例)

Class<?> clazz = Object.class // 类名.class 
Class<?> clazz = object.getClass() //对象.getClass()    
Class<?> clazz = Class.forName("ClassName") // 在编译时不能确定需要的是哪个类时使用

Class类中生成实例的方法:

Object newInstance() // 默认使用类的无参数构造器,如果创建有参数实例,需要先调用
    //getConstructors(),得到一个Constructor构造器的实例。   
object.getClass().newInstance()// 使用无参构造函数创建实例
clazz.getConstructor(String.class).newInstance(233) //获取String的构造函数,新建实例

Class类中获取类信息的方法:

Field[] getFields() // 获取成员变量
Method[] getMethods() // 获取方法
Constructor[] getConstructors() // 获取构造函数

java.lang.reflect类库中有三个类:

  • Field:描述类的域
  • Method:描述类的方法
  • Constructor:描述类的构造器

在Field类中:

public void set(Object obj, Object value) //可以修改任意对象的某成员变量值
    //参数1:对象  参数2:要修改的值

在Method类中:

 Public Object invoke(Object implicitPara,Object[] explicitPara) // 调用某类的任意方法
     //参数1:为实现类 参数2: 为方法参数

反射机制就是通过这些类库中类的方法实现动态获取类型信息。

在本文介紹RPC的过程客户端通过反射(Object.class.getMethod())获取接口代理类的方法信息,然后通过网络传递到服务端,服务端根据传来的方法名及参数(methodName``parameter)结合反射调用服务类(method.inovke())即被代理类的方法。

代理模式

给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。

这种方法有两个好处

  • 保证客户端对实现类的透明调用
  • 实现类扩展功能代码简洁

代理模式角色分为 3 种:

Subject(接口):定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;

RealSubject(接口的实现类):真正实现业务逻辑的类;

Proxy(代理类):用来代理和封装真实主题;

代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层即接口。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxjRqVZU-1571212028669)(https://github.com/chenqihang11233/picture/blob/master/csdn/daili.png?raw=true)]

代理模式按照职责(使用场景)来分类,至少可以分为以下几类:1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理等等。

如果根据字节码的创建时机来分类,可以分为静态代理和动态代理:

  • 所谓静态也就是在程序运行前就已经存在代理类的.class字节码文件,代理类和真实主题角色的关系在运行前就确定了
  • 而动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的.class字节码文件,即运行前代理类并不知道要代理谁

静态代理

现在学习一下静态代理,直观感受一下代理模式的用处,理解静态代理的缺点,之后再介绍动态代理。

下面的是一个打官司的例子。首先创建一个诉讼接口类Ilawsuit,以及一个具体诉讼人XiaoGang

public interface ILawsuit {
   
    //提交申请
    void submit();
    
    //进行举证
    void burden();
    
    //开始辩护
    void defend();
    
    //诉讼完成
    void finish();
}

4个方法表示诉讼的一般流程。

public class XiaoGang implements ILawsuit {
   
    @Override
    public void submit() {
   
        //老板拖欠小刚工资 小刚只好申请仲裁
        System.out.println("老板拖欠工资!特此申请仲裁!");
    }
    @Override
    public void burden() {
   
        System.out.println("这是合同书和过去一年的银行工资流水!");
    }
    @Override
    public void defend() {
   
        System.out.println("证据确凿,无需多言!");
    }
    @Override
    public void finish() {
   
        System.out.println(
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值