1. 程式人生 > >手寫簡單 rpc 框架

手寫簡單 rpc 框架

手寫簡單 rpc 框架

0 緣起

一直對 rpc 的實現原理很好奇, 看了下別人實現的 rpc 框架, 感覺實現太複雜了,本文參考了 黃勇實現的 輕量級 rpc 框架,專注 rpc 核心功能。

1 技術選型

  • 序列化協議 :Protostuff , 它基於 Protobuf 序列化框架,面向 POJO,無需編寫 .proto 檔案
  • IOC框架:Spring, 後續考慮自己寫一個
  • 底層通訊框架:netty,它使 NIO 程式設計更加容易,遮蔽了 Java 底層的 NIO 細節。
  • 註冊中心:ZooKeeper 提供服務註冊與發現功能,開發分散式系統的必備選擇,同時它也具備天生的叢集能力

2 框架思路

該框架流程:

  • 1 服務端啟動, 和服務釋出
 1 根據 配置的 zookeeper 資訊, 初始化 zookeeper 的連線,

 2 獲取 容器中 帶有 RpcService 註解的 bean

 3 將 服務名 和 服務實體 放入 handlerMap

 4 初始化 netty 監聽在指定埠

 5 遍歷 handlerMap , 向 zookeeper 中註冊 服務節點資訊
  • 2 客戶端呼叫
 1 初始化 serviceDiscovery, 用於在 zookeeper 中發現服務

 2 初始化 rpcProxy , rpc 代理類, 通過這個代理類,可以建立指定服務的代理物件。

 3 呼叫 rpcProxy 的 create 方法,指定服務類, 初始化代理物件

 4 執行 生成代理物件的方法的時候, 會被攔截,通過上面指定的 服務類,去註冊中心查詢指定服務, 獲取 服務的 ip 和 host

 5 封裝請求,通過 netty 初始化一個連線 傳送 該請求

 6 netty 接收到 請求以後,通過反射執行,並且返回結果

3 呼叫方式

3.1 定義服務

@RpcService(HelloService.class)
public class HelloServiceImpl implements HelloService {

    @Override
    public String hello(String name) {
        return "Hello! " + name;
    }
}

3.2 定義 bean

 <!-- 在 server 端 啟用註冊中心 -->
    <bean id="serviceRegistry" class="org.hwj.rpc.registry.center.zookeeper.ZooKeeperServiceRegistry">
        <constructor-arg name="zkAddress" value="${rpc.registry_address}"/>
    </bean>

    <bean id="rpcServer" class="org.hwj.rpc.server.RpcServer">
        <constructor-arg name="serviceAddress" value="${rpc.service_address}"/>
        <constructor-arg name="serviceRegistry" ref="serviceRegistry"/>
    </bean>

3.3 啟動服務

new ClassPathXmlApplicationContext("spring.xml");
System.out.println("start server...");

3.4 服務呼叫

 ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
 RpcProxy rpcProxy = context.getBean(RpcProxy.class);

 HelloService helloService = rpcProxy.create(HelloService.class);
 String result = helloService.hello("World");
 System.out.println(result);

4 完整程式碼

https://github.com/junjun888/simple-rpc

5 參考

https://my.oschina.net/huangyong/blog/361751