7天用Go動手寫/從零實現RPC框架GeeRPC
0 目錄
- 第一天 - 服務端與訊息編碼 | Code
- 第二天 - 支援併發與非同步的客戶端 | Code
- 第三天 - 服務註冊(service register) | Code
- 第四天 - 超時處理(timeout) | Code
- 第五天 - 支援HTTP協議 | Code
- 第六天 - 負載均衡(load balance) | Code
- 第七天 - 服務發現與註冊中心(registry) | Code
1 談談 RPC 框架
RPC(Remote Procedure Call,遠端過程呼叫)是一種計算機通訊協議,允許呼叫不同程式空間的程式。RPC 的客戶端和伺服器可以在一臺機器上,也可以在不同的機器上。程式設計師使用時,就像呼叫本地程式一樣,無需關注內部的實現細節。
不同的應用程式之間的通訊方式有很多,比如瀏覽器和伺服器之間廣泛使用的基於 HTTP 協議的 Restful API。與 RPC 相比,Restful API 有相對統一的標準,因而更通用,相容性更好,支援不同的語言。HTTP 協議是基於文字的,一般具備更好的可讀性。但是缺點也很明顯:
- Restful 介面需要額外的定義,無論是客戶端還是服務端,都需要額外的程式碼來處理,而 RPC 呼叫則更接近於直接呼叫。
- 基於 HTTP 協議的 Restful 報文冗餘,承載了過多的無效資訊,而 RPC 通常使用自定義的協議格式,減少冗餘報文。
- RPC 可以採用更高效的序列化協議,將文字轉為二進位制傳輸,獲得更高的效能。
- 因為 RPC 的靈活性,所以更容易擴充套件和整合諸如註冊中心、負載均衡等功能。
2 RPC 框架需要解決什麼問題
RPC 框架需要解決什麼問題?或者我們換一個問題,為什麼需要 RPC 框架?
我們可以想象下兩臺機器上,兩個應用程式之間需要通訊,那麼首先,需要確定採用的傳輸協議是什麼?如果這個兩個應用程式位於不同的機器,那麼一般會選擇 TCP 協議或者 HTTP 協議;那如果兩個應用程式位於相同的機器,也可以選擇 Unix Socket 協議。傳輸協議確定之後,還需要確定報文的編碼格式,比如採用最常用的 JSON 或者 XML,那如果報文比較大,還可能會選擇 protobuf 等其他的編碼方式,甚至編碼之後,再進行壓縮。接收端獲取報文則需要相反的過程,先解壓再解碼。
解決了傳輸協議和報文編碼的問題,接下來還需要解決一系列的可用性問題,例如,連線超時了怎麼辦?是否支援非同步請求和併發?
如果服務端的例項很多,客戶端並不關心這些例項的地址和部署位置,只關心自己能否獲取到期待的結果,那就引出了註冊中心(registry)和負載均衡(load balance)的問題。簡單地說,即客戶端和服務端互相不感知對方的存在,服務端啟動時將自己註冊到註冊中心,客戶端呼叫時,從註冊中心獲取到所有可用的例項,選擇一個來呼叫。這樣服務端和客戶端只需要感知註冊中心的存在就夠了。註冊中心通常還需要實現服務動態新增、刪除,使用心跳確保服務處於可用狀態等功能。
再進一步,假設服務端是不同的團隊提供的,如果沒有統一的 RPC 框架,各個團隊的服務提供方就需要各自實現一套訊息編解碼、連線池、收發執行緒、超時處理等“業務之外”的重複技術勞動,造成整體的低效。因此,“業務之外”的這部分公共的能力,即是 RPC 框架所需要具備的能力。
3 關於 GeeRPC
Go 語言廣泛地應用於雲端計算和微服務,成熟的 RPC 框架和微服務框架汗牛充棟。grpc
、rpcx
、go-micro
等都是非常成熟的框架。一般而言,RPC 是微服務框架的一個子集,微服務框架可以自己實現 RPC 部分,當然,也可以選擇不同的 RPC 框架作為通訊基座。
考慮效能和功能,上述成熟的框架程式碼量都比較龐大,而且通常和第三方庫,例如 protobuf
、etcd
、zookeeper
等有比較深的耦合,難以直觀地窺視框架的本質。GeeRPC 的目的是以最少的程式碼,實現 RPC 框架中最為重要的部分,幫助大家理解 RPC 框架在設計時需要考慮什麼。程式碼簡潔是第一位的,功能是第二位的。
因此,GeeRPC 選擇從零實現 Go 語言官方的標準庫 net/rpc
,並在此基礎上,新增了協議交換(protocol exchange)、註冊中心(registry)、服務發現(service discovery)、負載均衡(load balance)、超時處理(timeout processing)等特性。分七天完成,最終程式碼約 1000 行。
附 推薦閱讀
原文地址: 7天用Go從零實現RPC框架GeeRPC - 極客兔兔
關注知乎: 極客兔兔
關注微博: @極客兔兔
相關文章
- 7天用Go動手寫/從零實現ORM框架GeeORMGoORM框架
- 從零開始實現一個RPC框架(零)RPC框架
- java 從零開始手寫 RPC (01) 基於 websocket 實現JavaRPCWeb
- 從零開始實現一個RPC框架(五)RPC框架
- 從零開始實現一個RPC框架(四)RPC框架
- 從零開始實現一個RPC框架(三)RPC框架
- 從零開始實現一個RPC框架(二)RPC框架
- 從零開始實現一個RPC框架(一)RPC框架
- [7 天用 Go 從零實現系列] 之 Web 框架 GeeGoWeb框架
- 手寫RPC框架RPC框架
- 從零開始實現一個分散式RPC框架分散式RPC框架
- Go 實現簡易 RPC 框架GoRPC框架
- 從零開始實現一個IDL+RPC框架RPC框架
- 從零開始實現簡單 RPC 框架 1:RPC 框架的結構和設計RPC框架
- 從零實現一個RPC框架系列文章(二):11個類實現簡單RPCRPC框架
- 01 . Go之從零實現Web框架(類似Gin)GoWeb框架
- 從零開始實現簡單 RPC 框架 4:註冊中心RPC框架
- 從零實現一個RPC框架系列文章(一):思路篇RPC框架
- java 從零開始手寫 RPC (05) reflect 反射實現通用呼叫之服務端JavaRPC反射服務端
- java 從零開始手寫 RPC (04) -序列化JavaRPC
- 從零手寫實現 nginx-21-modules 模組Nginx
- 從零手寫實現 nginx-27-return 指令Nginx
- 從零開始手寫Koa2框架框架
- 從零手動實現簡易TomcatTomcat
- 從零手寫實現 tomcat-03-基本的 socket 實現Tomcat
- 從零手寫實現 nginx-29-try_files 指令Nginx
- 從零開始實現簡單 RPC 框架 2:擴充套件利器 SPIRPC框架套件
- 從零開始實現簡單 RPC 框架 3:配置匯流排 URLRPC框架
- [從RPC到Go-Micro 壹]Go語言實現RPC程式設計RPCGoC程式程式設計
- 從零手寫實現 nginx-35-proxy_pass netty 如何實現?NginxNetty
- 從零手寫實現 nginx-03-nginx 基於 Netty 實現NginxNetty
- 基於netty手寫RPC框架NettyRPC框架
- 仿照dubbo手寫一個RPC框架RPC框架
- 手寫RPC框架(六)整合NettyRPC框架Netty
- 大廚小鮮——基於Netty自己動手實現RPC框架NettyRPC框架
- 從零手寫實現 tomcat-05-servlet 處理支援TomcatServlet
- 從零手寫實現 tomcat-09-servlet 處理類TomcatServlet
- 從零手寫實現 tomcat-11-filter 過濾器TomcatFilter過濾器