目录
目录README.md

基于 Java 1.8 和 Python 3.8 的简易RPC框架

Change Log

@qinjc

2024.04.08

  • Python IDL编译
  • Python RPC框架之客户端(即可以向Java的服务端请求调用)
  • Python RPC框架之服务端(即可以接收来自Java客户端的请求)

2024.04.07

  • 将调用请求和返回的RPC通信协议报文从Java Object(仅限Java使用)改为JSON字符串(与语言无关)

2024.04.05

  • Java JSON IDL编译

2024.04.03

  • 基于动态代理+反射机制并通过Socket通信让Client可以远程调用Server中的功能
  • 编写java的IDL文件
  • 定义简易RPC协议(请求与回复),预计包含header和body字段,header中包含版本信息,body中包含远程调用所需的信息:Request包含接口名,方法名,参数类型,参数值;Response包含返回的Object
  • 实现简易RPC协议请求与回复报文进行编解码
  • 在服务端实现IDL接口
  • 基于写好的IDL文件完成客户端的方法调用
  • 改造Server,使其能开启一个线程,完成一次远程调用过程(接收、解析、反射调用、编码、发送)
  • 改造Client,使其的动态代理完成一次远程调用过程(方法参数编码、构造请求报文、数据流发送接收、解析回复报文、返回值的解码)
  • 构造不同的IDL文件进行测试

2024.04.02

  • 通过JDK reflect实现Java动态代理

Todo List

  • Java语言实现对象的静态代理
  • 通过JDK reflect实现动态代理
  • 仅支持Java单语言的RPC框架
  • 多语言支持(采用XML作为结构化接口描述语言)XML的解析太麻烦了,还是JSON简单
  • 多语言支持(采用JSON作为结构化接口描述语言)
    • Java JSON IDL编译
    • Python JSON IDL编译
    • C/C++ JSON IDL编译
  • 将客户端与服务端之间的通信从Java Object变为纯字符串,字符串内容为JSON格式(将通信协议与编程语言解耦)
  • 研究Python语言的动态代理或反射机制
  • 支持Python语言的RPC框架之客户端
  • 支持Python语言的RPC框架之服务端

Run

  1. 运行Test目录下的ServerTest.java或ServerTest.py开启服务端
  2. 运行Test目录下的ClientTest.java或ClientTest.py开启客户端

    服务端为Java实现,客户端为Python调用

    服务端为Python实现,客户端为Java调用

添加新的IDL

本项目使用JSON格式定义IDL,将其放在src/main/java/rpc/IDL/中(如Example.json

{
  "name": "Example",
  "methods": [
    {
      "name": "foo1",
      "description": "example description",
      "parameters": [
      ],
      "returns": {
        "type": "void"
      }
    },
    {
      "name": "foo2",
      "description": "example description",
      "parameters": [
        {
          "name": "bar1",
          "type": "int",
          "description": "The first number bar1"
        },
        {
          "name": "bar2",
          "type": "float",
          "description": "The second number bar2"
        }
      ],
      "returns": {
        "type": "int",
        "description": "example return description"
      }
    }
  ]
}

Java语言的IDL编译

  1. 运行src/main/java/rpc/IDL/JavaInterfaceGenerate.java中generate方法,参数为IDL中文件名及name字段
    JavaInterfaceGenerate.generate("Example");
  2. 程序会自动将IDL文件编译为Java interface文件(src/main/java/rpc/IDL/Example.java
    package rpc.IDL;
    public interface Example {
        void foo1();
        int foo2(int bar1, float bar2);
    }
  3. 在**src/test/java/rpc/server/ImplementLib/**中添加对应的实现(ExampleImpl.java)
    package rpc.server.ImplementLib;
    
    public class ExampleImpl implements Example {
        @Override
        public void foo1() {
            // 具体实现
        }
    
        @Override
        public int foo2(int bar1, float bar2) {
            // 具体实现
            return 0;
        }
    }
  4. src/test/java/rpc/server/ServerTest.java中将新的类添加进server
    rpc_server.addService(new ExampleImpl());
  5. src/test/java/rpc/client/ClientTest.java中,先通过RPC代理handle获取代理对象,随后像调用本地方法一样调用代理对象的方法即可
    // 创建对象代理
    Example example_proxy = handler.getProxy(Example.class);
    // 调用方法
    example_proxy.foo1();
    int ret = example_proxy.foo2(1, 2);
    System.out.println(ret);

Python语言的IDL编译

  1. 运行src/main/python/rpc/IDL/PythonInterfaceGenerate.py中PythonClassGenerator类的generate_file方法,参数为IDL中文件名及name字段
    PythonClassGenerator().generate_file("Example")
  2. 程序会自动将IDL文件编译为Python class文件(src/main/python/rpc/IDL/Example.py
    class Example:
        def foo1():
            pass
        
        def foo2(self, bar1: int, bar2: float) -> int:
            pass
  3. 在**src/test/python/rpc/server/ImplementLib/**中添加对应的实现(Example.py)
    class Example:
        def foo1():
            # 具体实现
            pass
        
        def foo2(self, bar1: int, bar2: float) -> int:
            # 具体实现
            return 0
  4. src/test/python/rpc/server/ServerTest.py中将新的类添加进server
    for service_name in ['Example', ...]:
        ...
  5. src/test/python/rpc/client/ClientTest.py中,先通过RPC代理ClientStub获取代理对象**service,随后像调用本地方法一样调用代理对象的方法即可
    // 创建对象代理
    clientStub = ClientStub()
    service = clientStub.get_service('Example')
    // 调用方法
    ret = service.foo2(1, 2)
    print(ret)
关于
2.4 MB
邀请码