1 萬行代碼,單機 50 萬 QPS,今年最值得學習的開源 RPC 框架!

又發現一個不錯的,工業級的,高性能 RPC 框架 srpc,分享給大家。

(1)RPC 簡介;

(2)行業常見 RPC 框架;

(3)srpc 特點;

(4)srpc 上手指南,demo 示例;

(5)srpc 架構設計;

(6)srpc 相關資料與資源;

文章較長,建議提前收藏。

什麼是 RPC?

Remote Procedure Call,遠程過程調用。

什麼是 “遠程”,爲什麼 “遠”?

先來看下什麼是 “近”,即 “本地函數調用”。

當我們寫下:

int result = Add(1, 2);

這行代碼的時候,到底發生了什麼?

(1)傳遞兩個入參;

(2)調用了本地代碼段中的函數,執行運算邏輯;

(3)返回一個出參;

這三個動作,都發生在同一個進程空間裏,這是本地函數調用。

那有沒有辦法,調用一個跨進程的函數呢?

典型的,這個進程部署在另一臺服務器上。

最容易想到的,兩個進程約定一個協議格式,使用 Socket 通信,來傳輸:

(1)入參;

(2)調用哪個函數;

(3)出參;

如果能夠實現,那這就是 “遠程” 過程調用。

爲什麼需要 RPC 框架呢?

如果沒有統一的 RPC 框架,各個團隊的服務提供方就需要各自實現一套序列化、反序列化、網絡框架、連接池、收發線程、超時處理、狀態機等 “業務之外” 的重複技術勞動,造成整體的低效。

RPC 框架的職責,就是要屏蔽各種複雜性:

(1)調用方 client 感覺就像調用本地函數一樣,來調用服務;

(2)提供方 server 感覺就像實現一個本地函數一樣,來實現服務;

有哪些常見的,出圈的 RPC 框架呢?

(1)gRPC,Google 出品,支持多語言;

(2)Thrift,Facebook 出品,支持多語言;

(3)Dubbo,阿里開源的,支持 Java;

(4)bRPC,百度開源的,支持 C++,Java;

(5)tRPC,騰訊 RPC 框架,支持多語言;

(6)...

畫外音:還有哪些?

今天和大家分享的 srpc,作者是搜狗的媛架構師 liyingxin,基於 WF,代碼量 1W 左右:

(1)非常適合用來學習 RPC 的架構設計;

(2)又是一個工業級的產品,QPS 可以到 50W,應該是行業能目前性能最好的 RPC 框架了吧,有不少超高併發的線上應用都使用它。

畫外音:不服?來戰!

什麼是 srpc?

基於 WF 的輕量級,超高性能,工業級 RPC 框架,兼容多協議,例如百度 bRPC,騰訊 tRPC,Google 的 gRPC,以及 FB 的 thrift 協議。

srpc 有些什麼特點?

(1)支持多種 IDL 格式,包括 Protobuf,Thrift 等,對於這類項目,可以一鍵遷移;

(2)支持多種序列化方式,包括 Protobuf,Thrift,json 等;

(3)支持多壓縮方法,對應用透明,包括 gzip,zlib,lz4,snappy 等;

(4)支持多協議,對應用透明,包括 http,https,ssl,tcp 等;

(5)高性能;

不同客戶端線程壓力下的性能表現非常穩定,QPS 在 50W 左右,優於同等壓測配置的 bRPC 與 thrift。

(6)輕量級,低門檻,1W 行左右代碼,只需引入一個靜態庫;

如何快速上手,體驗這個帥氣的 RPC 框架呢?

簡單來說,只需要三個步驟。

第一步:定義 IDL 描述文件。

syntax = "proto3";// proto2 or proto3

message EchoRequest {

_   string message = 1;_

_   string name = 2;_

};

message EchoResponse {

_   string message = 1;_

};

service Example {

_   rpc Echo(EchoRequest) returns (EchoResponse);_

};

第二步:生成代碼,並實現 ServiceIMPL,server 端就搞定了。

class ExampleServiceImpl : public Example::Service

{

public:

_   void Echo(EchoRequest *request,_

_        EchoResponse *response,_

_        RPCContext *ctx) override_

_    {_

_       response->set_message("Hi," + request->name());_

_    }_

};

make 一把,一氣呵成。

第三步:自己定義一個請求客戶端,向服務端發送 echo 請求。

int main()

{

_   Example::SRPCClient client("127.0.0.1", 1412);_

_   EchoRequest req;_

_   req.set_message("Hello, srpc!");_

_   req.set_name("zhangsan");_

_   client.Echo(&req, _

_        [](EchoResponse *response, RPCContext *ctx){});_

_   return 0;_

}

文末的資料集裏,有非常詳細的手冊鏈接,一步步照着來就行。

srpc 的架構設計思路是怎樣的?

作爲一個 RPC 框架,srpc 的架構是異常清晰的,用戶需要關注這 3 個層次:

(1)IDL 接口描述文件層

(2)RPC 序列化協議層

(3)網絡通訊層

同時,每一層次又提供了多種選擇,用戶可以任意的組合:

如上圖所示:

(1)IDL 層,用戶可以選擇 Protobuf 或者 Thrift;

(2)協議層,可以選擇 Thrift,bRPC,tRPC 等;

畫外音:因此,才能和其他 RPC 框架無縫互通。

(3)通信層,可以選擇 tcp 或者 http;

在此分層架構之下,RPC 的客戶端要做什麼工作,RPC 的服務端要做什麼工作,srpc 框架又做了什麼工作呢?

首先必須在 IDL 中要定義好:

(1)邏輯請求包 request;

(2)邏輯響應包 response;

(3)服務接口函數 method;

RPC-client 的工作就異常簡單了:

(1)調用 method;

(2)綁定回調函數,處理回調;

對應上圖中頂部方框的綠色部分。

RPC-server 的工作也非常簡單,像實現一個本地函數一樣,提供遠程的服務:

(1)實現 method;

(2)接受 request,邏輯處理,返回 response;

對應上圖中底部方框的黃色部分。

srpc 框架完成了絕大部分的工作:

(1)對 request 序列化,壓縮,處理生成二進制報文;

(2)連接池,超時,任務隊列,異步等處理;

(3)對 request 二進制報文處理,解壓縮,反序列化;

...

對應上圖中中間的方框的紅色部分,以及大部分流程。

在這個過程中,srpc 採用插件化設計,各種複雜性細節,對接口調用方與服務提供方,都是透明的,並且具備良好的擴展性

如上圖所示,用戶只需要關注 IDL,即邏輯請求,響應,接口的調用與實現。框架層面,將各種能力以插件的方式集成進來,向用戶提供不同能力的組合選擇。

另外,定義好 IDL 之後,服務端的代碼可以利用框架提供的工具自動生成代碼,業務服務提供方,只需要專注於業務接口的實現即可,你說帥氣不帥氣?

畫外音:具體的生成工具,與生成方法,請參看 git 上的文檔。

最後,我覺得這個 srpc 最帥氣的地方之一,就是:開源版本即線上工程版本,更新快,issue 響應快,並且文檔真的很全!

畫外音:不少大公司,公司內部的版本和開源的版本是兩套代碼,開源版本沒有文檔,KPI 完成之後,開源就沒人維護了,結果坑了一大票人。

文章的結尾,分享一些學習資源吧。

項目地址:https://github.com/sogou/srpc

項目 demo:

README_cn.md

項目架構設計:

docs/wiki.md

作者知乎:

https://www.zhihu.com/people/liyingxin1412/posts

作者聯繫方式:

發現 bug 可以隨時提交給她,響應絕對快速。

項目地址https://github.com/sogou/srpc

Star:800+

畫外音:srpc 還有很多優秀的設計,等待大家去挖掘。

末了,希望這個 1W 行代碼的 RPC 框架,能夠幫助大家更透徹的瞭解 RPC 的底層原理。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ax1646PKHdTkRu6Pv8ijrQ