手寫簡單 rpc 框架
阿新 • • 發佈:2018-11-19
手寫簡單 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);