Angular8正式發布了,Java13再過幾個月也要發布了,技術迭代這么快,框架的復雜度越來越大,但是原理是基本不變的。所以沉下心看清代碼本質很重要,這次給大家帶來的是手寫RPC框架。
完整代碼以及說明文檔,點我跳躍~
1. 什么是RPC?
RPC是指遠程過程調用,也就是說兩台服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的函數/方法,由於不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。
RPC框架有很多,比較知名的如阿里的Dubbo、google的gRPC、Go語言的rpcx、Apache的thrift,新浪的motan等等。當然了,你也可以說Dubbo是RPC框架的超集,此外對於Spring Cloud來說,RPC也只是它的一個功能模塊。(話說Dubbo已經晉升為Apache頂級項目了,還不一起動手學習下?)
RPC要解決的兩個問題:
- 解決分布式系統中,服務之間的調用問題。
- 遠程調用時,要能夠像本地調用一樣方便,讓調用者感知不到遠程調用的邏輯。
2. 技術選型
-
SpringBoot
項目的基礎框架,提供IoC功能。同時方便打成JAR包,便於測試。 -
Netty
基於NIO的網絡通信框架。相比用java socket實現的BIO通信,Netty無論是代碼編寫簡潔還是基於NIO異步非阻塞特性,都占盡了優勢。 -
fastjson
序列化、反序列化。RPC框架中通信選擇有很多:kyro/thift/json/hessian/protobuf/xml等等,為了快速實現RPC框架,節省生成樁函數的時間成本,所以本文采用了阿里的fastjson。 -
zookeeper
提供服務的發現與注冊。一個服務會有多個實例,所以我們選用zookeeper作為注冊中心,在調用時,從zookeeper獲取服務的實例列表,再從中選擇進行調用。
3. RPC實現流程
消費者端流程:
- 代理服務接口
- 服務發現(連接zookeeper,獲取生產者列表)
- 遠程調用(輪詢生產者服務列表),將類名,方法名和參數等信息通過代理發送給生產者端
生產者端流程:
- 加載需要遠程調用的服務,並緩存
- 啟動通訊服務器(Netty)
- 服務注冊(把通信地址放入zookeeper)
- 收到消息后使用反射,本地調用方法並將執行的結果編碼返回給消費者端
在調用鏈路中斷點,就可以同時了解RPC通信原理和Netty的通信原理了,代碼每個方法和類都做了注釋~實踐出真知,看代碼勝過所有博客的文字介紹。
4. 未實現的功能
相比Dubbo這樣成熟的RPC框架還有未實現的功能如下:
- 負載均衡
如何從多個實例里挑選一個出來,進行調用,這就要用到負載均衡了。負載均衡的策略肯定不只一種,要怎樣把策略做成可配置的?又要如何實現這些策略? - 結果緩存
每次調用查詢接口時都要真的去Server端查詢嗎?是不是要考慮一下支持緩存? - 多版本控制
服務端接口修改了,舊的接口怎么辦? - 異步調用
客戶端調用完接口之后,不想等待服務端返回,想去干點別的事,如何支持? - 優雅停機
服務端要停機了,還沒處理完的請求,如何優雅的處理?
最后,限於筆者經驗水平有限,歡迎讀者就文中的觀點提出寶貴的建議和意見。如果想獲得更多的學習資源或者想和更多的是技術愛好者一起交流,可以關注我的公眾號『全菜工程師小輝』后台回復關鍵詞領取學習資料、進入前后端技術交流群和程序員副業群。同時也可以加入程序員副業群Q群:735764906 一起交流。