日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

RPC(Remote Procedure Call),是一個大家既熟悉又陌生的詞,只要涉及到通信,必然需要某種網絡協議。我們很可能用過HTTP,那么RPC又和HTTP有什么區別呢?RPC還有什么特點,常見的選型有哪些?

1. RPC是什么

RPC可以分為兩部分:用戶調用接口 + 具體網絡協議。前者為開發者需要關心的,后者由框架來實現。

舉個例子,我們定義一個函數,我們希望函數如果輸入為“Hello World”的話,輸出給一個“OK”,那么這個函數是個本地調用。如果一個遠程服務收到“Hello World”可以給我們返回一個“OK”,那么這是一個遠程調用。我們會和服務約定好遠程調用的函數名。因此,我們的用戶接口就是:輸入、輸出、遠程函數名,比如用 SRPC 開發的話,client端的代碼會長這樣:

int main()
{
    Example::SRPCClient client(IP, PORT);
    EchoRequest req; // 用戶自定義的請求結構
    EchoResponse resp; // 用戶自定義的回復結構

    req.set_message("Hello World");
    client.Echo(&req, &resp, NULL); // 調用遠程函數名為Echo
    return 0;
}

具體網絡協議,是框架來實現的,把開發者要發出和接收的內容以某種應用層協議打包進行網絡收發。這里可以和HTTP進行一個明顯的對比:

  • HTTP也是一種網絡協議,但包的內容是固定的,必須是:請求行 + 請求頭 + 請求體;
  • RPC是一種自定義網絡協議,由具體框架來定,比如SRPC里支持的RPC協議有:SRPC/thrift/BRPC/tRPC

這些RPC協議都和HTTP平行,是應用層協議。我們再進一步思考,HTTP只包含具體網絡協議,也可以返回比如我們常見的HTTP/1.1 200 OK,但仿佛沒有用戶調用接口,這是為什么呢?

這里需要搞清楚,用戶接口的功能是什么?最重要的功能有兩個:

  • 定位要調用的服務;
  • 讓我們的消息向前/向后兼容;

我們用一個表格來看一下HTTP和RPC分別是怎么解決的:

一文帶你搞懂RPC到底是個啥

 

因此,HTTP的調用減少了用戶調用接口的函數,但是犧牲了一部分消息向前/向后兼容的自由度。但是,開發者可以根據自己的習慣進行技術選型,因為RPC和HTTP之間大部分都是協議互通的!是不是很神奇?接下來我們看一下RPC的層次架構,就可以明白為什么不同RPC框架之間、以及RPC和HTTP協議是如何做到互通的。

2. RPC有什么

我們可以從SRPC的架構層次上來看,RPC框架有哪些層,以及SRPC目前所橫向支持的功能是什么:

  • 用戶代碼(client的發送函數/server的函數實現)
  • IDL序列化(protobuf/thrift serialization)
  • 數據組織 (protobuf/thrift/json)
  • 壓縮(none/gzip/zlib/snAppy/lz4)
  • 協議 (Sogou-std/Baidu-std/Thrift-framed/TRPC)
  • 通信 (TCP/HTTP)

我們先關注以下三個層級:

一文帶你搞懂RPC到底是個啥

 

如圖從左到右,是用戶接觸得最多到最少的層次。IDL層會根據開發者定義的請求/回復結構進行代碼生成,目前小伙伴們用得比較多的是protobuf和thrift,而剛才說到的用戶接口和前后兼容問題,都是IDL層來解決的。SRPC對于這兩個IDL的用戶接口實現方式是:

  • thrift:IDL純手工解析,用戶使用srpc是不需要鏈thrift的庫的 !!!
  • protobuf:service的定義部分純手工解析

中間那列是具體的網絡協議,而各RPC能互通,就是因為大家實現了對方的“語言”,因此可以協議互通。

而RPC作為和HTTP并列的層次,第二列和第三列理論上是可以兩兩結合的,只需要第二列的具體RPC協議在發送時,把HTTP相關的內容進行特化,不要按照自己的協議去發,而按照HTTP需要的形式去發,就可以實現RPC與HTTP互通。
 

3. RPC的生命周期

到此我們可以通過SRPC看一下,把request通過method發送出去并處理response再回來的整件事情是怎么做的:

一文帶你搞懂RPC到底是個啥

 

根據上圖,可以更清楚地看到剛才提及的各個層級,其中壓縮層、序列化層、協議層其實是互相解耦打通的,在SRPC代碼上實現得非常統一,橫向增加任何一種壓縮算法或IDL或協議都不需要也不應該改動現有的代碼,才是一個精美的架構~

我們一直在說生成代碼,到底有什么用呢?圖中可以得知,生成代碼是銜接用戶調用接口和框架代碼的橋梁,這里以一個最簡單的protobuf自定義協議為例:example.proto

syntax = "proto3";

message EchoRequest
{
    string message = 1;
};

message EchoResponse
{
    string message = 1;
};

service Example
{
    rpc Echo(EchoRequest) returns (EchoResponse);
};

我們定義好了請求、回復、遠程服務的函數名,通過以下命令就可以生成出接口代碼example.srpc.h:

protoc example.proto --cpp_out=./ --proto_path=./
srpc_generator protobuf ./example.proto ./

我們一窺究竟,看看生成代碼到底可以實現什么功能:

// SERVER代碼
class Service : public srpc::RPCService
{
public:
    // 用戶需要自行派生實現這個函數,與剛才pb生成的是對應的
    virtual void Echo(EchoRequest *request, EchoResponse *response,
                      srpc::RPCContext *ctx) = 0;
};

// CLIENT代碼
using EchoDone = std::function<void (echoresponse *, srpc::rpccontext *)>;

class SRPCClient : public srpc::SRPCClient 
{
public:
    // 異步接口
    void Echo(const EchoRequest *req, EchoDone done);
    // 同步接口
    void Echo(const EchoRequest *req, EchoResponse *resp, srpc::RPCSyncContext *sync_ctx);
    // 半同步接口
    WFFuture<std::pair<echoresponse, srpc::rpcsynccontext>> async_Echo(const EchoRequest *req);
};

作為一個高性能RPC框架,SRPC生成的client代碼中包括了:同步、半同步、異步接口,文章開頭展示的是一個同步接口的做法。

而server的接口就更簡單了,作為一個服務端,我們要做的就是收到請求->處理邏輯->返回回復,而這個時候,框架已經把剛才提到的網絡收發、解壓縮、反序列化等都給做好了,然后通過生成代碼調用到用戶實現的派生service類的函數邏輯中。

由于一種協議定義了一種client/server,因此其實我們同樣可以得到的server類型有第二部分提到過的若干種:

  • SRPCServer
  • SRPCHttpServer
  • BRPCServer
  • TRPCServer
  • ThriftServer
  • ...

4. 一個完整的server例子

最后我們用一個完整的 server 例子,來看一下用戶調用接口的使用方式,以及如何跨協議使用HTTP作為client進行調用。剛才提到,srpc_generator 在生成接口的同時,也會自動生成空的用戶代碼,我們這里打開 server.pb_skeleton.cc 直接改兩行,即可 run 起來:

#include "example.srpc.h"
#include "workflow/WFFacilities.h"

using namespace srpc;
static WFFacilities::WaitGroup wait_group(1);

void sig_handler(int signo)
{
    wait_group.done();
}

class ExampleServiceImpl : public Example::Service
{
public:

    void Echo(EchoRequest *request, EchoResponse *response, srpc::RPCContext *ctx) override
    {
        response->set_message("OK"); // 具體邏輯在這里添加,我們簡單地回復一個OK
    }
};

int main()
{
    unsigned short port = 80; // 因為要啟動Http服務
    SRPCHttpServer server; // 我們需要構造一個SRPCHttpServer

    ExampleServiceImpl example_impl;
    server.add_service(&example_impl);

    server.start(port);
    wait_group.wait();
    server.stop();
    return 0;
}

只要安裝了srpc,linux下即可通過以下命令編譯出可執行文件:

g++ -o server server.pb_skeleton.cc example.pb.cc -std=c++11 -lsrpc

接下來是激動人心的時刻了,我們用人手一個的curl來發起一個HTTP請求:

$ curl -i 127.0.0.1:80/Example/Echo -H 'Content-Type: application/json' -d '{message:"Hello World"}'
HTTP/1.1 200 OK
SRPC-Status: 1
SRPC-Error: 0
Content-Type: application/json
Content-Encoding: identity
Content-Length: 16
Connection: Keep-Alive

{"message":"OK"}

5. 總結

今天我們基于 C++ 實現的開源項目 SRPC 深入分析了 RPC 的基本原理。SRPC 整體代碼風格簡潔、架構層次精巧,整體約1萬行代碼,如果你使用 C++,那可能非常適合你用來學習 RPC 架構。

通過這篇文章,相信我們可以清晰地了解到 RPC 是什么,接口長什么樣,也可以通過與HTTP協議互通來理解協議層次,更重要的是可以知道具體縱向的每個層次,及橫向對比我們常見的每種使用模式都有哪些。如果小伙伴對更多功能感興趣,也可以通過閱讀 SRPC 源碼進行進一步了解。

分享到:
標簽:RPC
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定