gRPC知識歸檔

文章目錄

  • gRPC知識歸檔
    • gRPC原理
      • 什么是gRPC
      • gRPC的特性
      • gRPC支持語言
      • gRPC使用場景
      • gRPC設計的動機和原則
    • 數據封裝和數據傳輸問題
      • 網絡傳輸中的內容封裝和數據體積問題
      • JSON
      • Protobuf(微服務之間的服務器調用,一般采用二進制序列化,比如protobuf)
      • 網絡傳輸效率問題
    • gRPC的4種模式
      • 一元RPC模式
      • 服務端流RPC模式
      • 客戶端流RPC
      • 雙向流RPC模式
    • gRPC同步異步
      • gRPC調用關系圖
      • proto文件
      • Client
      • server
      • 異步相關概念
        • 異步Client
        • 異步Server
        • 關系圖

gRPC知識歸檔

gRPC原理

什么是gRPC

RPC是遠程調用協議(Remote Procedure Call Protocol),可以讓我們像調用本地對象一樣發起遠程調用。RPC憑借強大的治理功能,成為解決分布式系統問題的一大利器。
gRPC是一個現代的,高性能的,開源的和語言無關的通用RPC框架,HTTP2協議設計,序列化使用PB(Protocol Buffer)高性能序列化框架,基于HTTP2+PB保證高性能。

在這里插入圖片描述

gRPC的Server和Client工作流程大致如下:

在這里插入圖片描述

  • tars兼容grpc
  • brpc也兼容grpc
  • grpc不兼容tars和brpc

gRPC的特性

  1. gRPC基于服務的思想:定義一個服務,描述這個服務的方法和出入參數,服務端有這個服務的具體實現,客戶端保有一個存根,提供與服務端相同的服務。
  2. gRPC默認采用protobuf作為IDL(Interface Description)接口描述語言,服務之間通信數據序列化和反序列化也是基于protocol buffer的,因為protocol buffer的特殊性,所以gRPC框架是跨語言的通信框架,可就是說用jave開發的gRPC服務,可以用GoLang,C++等語言調用。
  3. gRPC同時支持同步和異步調用,同步RPC調用會一直阻塞到服務端處完成返回數據,異步RPC是客戶端調用服務端時不等待服務端處理完成返回結果,而是服務端處理完成后主動回調客戶端高速客戶端處理完成。
  4. gRPC是基于HTTP2.0協議實現的,http2提供了很多新特性,并且在性能上相比http1提高了許多,所以gRPC的性能是非常好的。
  5. gRPC并沒有直接實現負載均衡和服務發現的功能,但是已經提供了自己的設計思路。已經為命名解析和負載均衡提供了接口。
  6. 基于http2的協議特性,gRPC允許自定義4類服務方法
    • 一元RPC
    • 服務端流式RPC
    • 客戶端流式RPC
    • 雙向流式RPC

gRPC支持語言

C++,Java(包括安卓),OC,Python,Ruby,Go,C#,Node.js。

gRPC使用場景

  1. 低延遲,高可擴展性的分布式系統
  2. 開發與云服務器的客戶端
  3. 設計一個準確,高效,與語言無關的新協議
  4. 分層設計,實現擴展,例如:身份驗證,負載平衡,日志記錄和監控。

gRPC設計的動機和原則

  1. 自由,開放:所有人,所有平臺都可以使用,開源,跨平臺,跨語言
  2. 協議可插拔:不同的服務需要使用不同的消息類型和編碼機制,例如,JSON,XML和Thirft,所以協議應允許可插拔機制,還有負載均衡,日志,監控等都支持可插拔機制。
  3. 阻塞和非阻塞:支持客戶端和服務器交換的消息序列的異步和同步處理。
  4. 取消和超時:一次RPC操作可能是持久并且昂貴的,應該允許客戶設置取消RPC通信和對這次通信加上超時時間。
  5. 拒絕:必須允許服務器通過在繼續處理請求的同時拒絕新請求的到來并且優雅地關閉
  6. 流處理:存儲系統依靠流和流控制來表達大型數據集,其他服務,如語音到文本或者股票行情,依賴流來表達與時間相關的消息序列。
  7. 流控制:計算能力和網絡容量在客戶端和服務器之間通常是不平衡的。流控制允許更好的緩沖區管理,以及過度活躍的對等提供DOS保護。
  8. 元數據交換:認證或跟蹤常見的跨領域問題依賴于不屬于服務器的接口數據交換。依賴他們的將這些特性演進到服務,暴露API來提供能力。
  9. 標準化狀態罵:客戶端通常以有限的方式相應API調用返回的錯誤。應約束狀態碼名稱空間,以使這些錯誤處理決策更加清晰。如果需要更加豐富的特定領域的狀態,則可以使用元數據交換機制來提供狀態。
  10. 互通性:報文協議必須遵循普通互聯網服務基礎框架

數據封裝和數據傳輸問題

網絡傳輸中的內容封裝和數據體積問題

早期的RPCJSON的方式,目前的RPC基本上都采用類似的Protobuf的二進制序列化方式。
其差別在于:json的設計是給人看的,protobuf的設計是給機器看的

JSON

優點:在body中對JSON內容編碼,極易跨語言,不需要約定特定的復雜編碼格式和Stub文件。在版本兼容性上很好,擴展容易。
缺點:JSON難以表達復雜的參數類型,如結構體等;數據冗余和低壓縮率使得傳輸特性能差。

Protobuf(微服務之間的服務器調用,一般采用二進制序列化,比如protobuf)

// XXXX.proto
// rpc服務的類 service關鍵字, Test服務類名
service Test {
// rpc 關鍵字,rpc的接口rpc HowRpcDefine (Request) returns (Response) ; // 定義一個RPC方法
}
// message 類,c++ class
message Request {
//類型 | 字段名字| 標號int64 user_id = 1;string name = 2;
}
message Response {repeated int64 ids = 1; // repeated 表示數組Value info = 2; // 可嵌套對象map<int, Value> values = 3; // 可輸出map映射
}
message Value {bool is_man = 1;int age = 2;
}

網絡傳輸效率問題

grpc采用HTTP2.0,相對于HTTP1.0在更快的傳輸更低的成本上做了改進。有一下幾個基本點:

  1. HTTP2未改變HTTP的語義(如GET/POST等),只是在傳輸上優化
  2. 引入幀,流的概念,在TCP連接中,可以區分多個request和response
  3. 一個域名只會有一個TCP連接,借助幀,流可以實現多路復用,降低資源消耗
  4. 引入二進制編碼,降低header帶來的空間占用
  • HTTP1.1核心問題在于:在同一個TCP連接中,沒辦法區分response是屬于哪個請求,一旦多個請求返回的文本內容混在一起,則沒法區分數據歸屬于哪個請求,所以請求只能一個個串行排隊發送。這直接導致了TCP資源的閑置。
  • HTTP2為了解決這個問題,提出了 流 的概念,每一次請求對應一個流,有一個唯一ID,用來區分不同的請求。基于流的概念,進一步提出了 幀 ,一個請求的數據會被分成多個幀,方便進行數據分割傳輸,每個幀都唯一屬于某一個流ID,將幀按照流ID進行分組,即可分離出不同的請求。這樣同一個TCP連接中就可以同時并發多個請求,不同請求的幀數據可穿插在一起,根據流ID分組即可。HTTP2.0基于這種二進制協議的亂序模式 (Duplexing),直接解決了HTTP1.1的核心痛點,通過這種復用TCP連接的方式,不用再同時建多個連接,提升了TCP的利用效率。

在這里插入圖片描述

gRPC的4種模式

一元RPC模式

一元RPC模式也被稱為簡單RPC模式,當客戶端調用服務端的遠程方法時,客戶端發送請求到服務端并且獲取一個響應,與響應一起發送的還有狀態細節以及trailer元數據。

在這里插入圖片描述

服務端流RPC模式

在服務器端流RPC模式中,服務器端在接受到客戶端額請求消息后,會發回一個響應的序列。這種多個響應所組成的序列被稱為。在將所有的服務器端響應發送完畢之后,服務器端會以trailer元數據的形式將其狀態發送給客戶端,從而標記流結束。

在這里插入圖片描述

客戶端流RPC

在客戶端流 RPC 模式中,客戶端會發送多個請求給服務器端,而不再是單個請求。服務器端則會發送一個響應給客戶端。但是,服務器端不一定要等到從客戶端接收到所有消息后才發送響應。基于這樣的邏輯,我們可以在接收到流中的一條消息或幾條消息之后就發送響應,也可以在讀取完流中的所有消息之后再發送響應。

在這里插入圖片描述

雙向流RPC模式

在雙向流RPC模式中,客戶端以消息流的形式發請求給服務端,服務端也以消息流的形式響應。調用必須有客戶端發起,但在此之后,通信完全基于gRPC客戶端和服務端的應用程序邏輯。

在這里插入圖片描述

gRPC同步異步

gRPC調用關系圖

在這里插入圖片描述

上圖列出了gRPC基礎概念及其關系圖。其中包括:Service(定義)、RPC、API、Client、Stub、Channel、Server、Service(實現)、ServiceBuilder等。

接下來,以官方提供的example/helloworld為例說明。

proto文件

syntax = "proto3";option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";package helloworld;// The greeting service definition.
service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.
message HelloRequest {string name = 1;
}// The response message containing the greetings
message HelloReply {string message = 1;
}

Client

class GreeterclientClient,是對Stub封裝;通過Stub可以真正調用RPC請求。

class GreeterClient {public:GreeterClient(std::shared_ptr<Channel> channel): stub_(Greeter::NewStub(channel)) {}// Assembles the client's payload, sends it and presents the response back// from the server.std::string SayHello(const std::string& user) {// Data we are sending to the server.HelloRequest request;request.set_name(user);// Container for the data we expect from the server.HelloReply reply;// Context for the client. It could be used to convey extra information to// the server and/or tweak certain RPC behaviors.ClientContext context;// The actual RPC.Status status = stub_->SayHello(&context, request, &reply);// Act upon its status.if (status.ok()) {return reply.message();} else {std::cout << status.error_code() << ": " << status.error_message()<< std::endl;return "RPC failed";}}private:std::unique_ptr<Greeter::Stub> stub_;
};

Channel提供一個特定gRPC server的主機和端口簡歷的連接。
Stub就是在Channel的基礎上創建而成。

target_str = "localhost:50051";
auto channel = grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials());
GreeterClient greeter(channel);
std::string user("world");
std::string reply = greeter.SayHello(user);

server

Server端需要實現對應的RPC,所有的RPC組成了Sevice

// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {Status SayHello(ServerContext* context, const HelloRequest* request,HelloReply* reply) override {std::string prefix("Hello ");reply->set_message(prefix + request->name());return Status::OK;}
};

Server的創建需要一個Builder,添加上監聽的地址和端口,注冊上該端口上綁定的服務,最后構建出Server并且啟動。

ServerBuilder builder;// Listen on the given address without any authentication mechanism.builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());// Register "service" as the instance through which we'll communicate with// clients. In this case it corresponds to an *synchronous* service.builder.RegisterService(&service);// Finally assemble the server.std::unique_ptr<Server> server(builder.BuildAndStart());

RPC和API的區別:RPC(Remote Procedure Call)是一次遠程過程調用的整個動作,而API(Application Programming Interface)是不同語言實現RPC中的具體接口。一個RPC可能對應多種API,比如同步的,異步的,回調的。

異步相關概念

不管Client還是Server,異步gRPC都是利用CompletionQueue API進行異步操作。基本流程:
- 綁定一個CompletionQueue到一個RPC調用
- 利用唯一的void* Tag進行讀寫
- 調用CompletionQueue::Next()等待操作完成,完成后通過唯一的Tag來判斷對應什么請求/返回進行后續操作

異步Client

greeter_async_client.cc中是異步Client的Demo,其中只有一次請求,邏輯簡單

  • 創建CompletionQueue
  • 創建RPC(即clientAsyncResponseReader<HelloReply>),這里有兩種方式:
    • stub_->PrepareAsyncSayHello() + rpc->StartCall()
    • stub_->AsyncSayHello()
  • 調用rpc->Finish()設置請求消息reply和唯一的tag關聯,將請求發送出去。
  • 使用cq.Next()等待Completion Queue返回響應消息體,通過tag關聯對應請求。
異步Server

RequestSayHello()這個函數沒有任何說明。只是說:“we request that the system start processing SayHello requset.”也沒有說和cq_->Next(&tag, &ok);的關系。我來說一下流程:
- 創建一個CallData,初始構造列表中將狀態設置為CREATE
- 構造函數中,調用Process()成員函數,調用service_->RequestSayHello()后,狀態變更為PROCESS:
- 傳入ServerContext ctx_
- 傳入HelloRequest request_
- 傳入ServerAsyncResponsewriter<HelloReply> responder_
- 傳入ServerCompletionQueue* cq_
- 將對象自身的地址作為tag傳入
- 該動作,能將事件加入事件循環,可以在CompletionQueue中等待
- 收到請求,cp->Next()的阻塞結束并且返回,得到tag,即上次傳入的CallData對象
- 調用tag對應CallData對象Process(),此時狀態Process
- 創建新的CallData對象以接受新請求
- 處理消息并且設置reply_
- 將狀態設置為FINISH
- 調用responder_.Finish()將返回發送給客戶端
- 該動作,能將事件加入到循環,可以將CompletionQueue中等待
- 發送完畢,cp->Next()的阻塞結束并且返回,得到tag。現實中,如果發送有異常應當有其他處理。
- 調用tag對應的CallData對象proceed,此時狀態為FINISHdelete this清理自己,一條消息處理完成。

關系圖

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713152.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713152.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713152.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

精讀《React Hooks 最佳實踐》

簡介 React 16.8 于 2019.2 正式發布&#xff0c;這是一個能提升代碼質量和開發效率的特性&#xff0c;筆者就拋磚引玉先列出一些實踐點&#xff0c;希望得到大家進一步討論。 然而需要理解的是&#xff0c;沒有一個完美的最佳實踐規范&#xff0c;對一個高效團隊來說&#x…

【airtest】自動化入門教程(二)airtest操作

目錄 一、touch 二、wait 三、swipe 四、exists 五、text 六、keyevent 七、snapshot 八、sleep 九、斷言 9.1 assert_exists 9.2 assert_not_exists 9.3 assert_equal 9.4 assert_not_equal 前言&#xff1a;本文主要針對aritest部分的基礎操作,aritest是一個跨平…

網絡編程第二天

1.基于TCP的通信(面向連接的通信) 服務器代碼實現&#xff1a; #include <myhead.h> #define IP "192.168.126.91" #define PORT 9999 int main(int argc, const char *argv[]) {//1、創建套接字int sfd-1;if((sfdsocket(AF_INET,SOCK_STREAM,0))-1){perror(…

LeetCode 76 最小覆蓋字串

LeetCode 76 最小覆蓋字串 在本篇博客中&#xff0c;我們將探討LeetCode上的一道算法題目——“最小覆蓋子串”。這道題的主要目標是找到字符串s中包含字符串t中所有字符的最小子串。 問題描述 給定字符串s和t&#xff0c;要求在字符串s中找到一個最小的子串&#xff0c;使得…

5.36 BCC工具之ucalls.py解讀

一,工具簡介 ucalls工具總結了包括Java、Perl、PHP、Python、Ruby、Tcl和Linux系統調用在內的各種高級語言中的方法調用。它顯示最常調用方法的統計信息,以及這些方法的延遲(持續時間)。 通過系統調用支持,ucalls可以提供關于進程與系統交互的基本信息,包括系統調用計數…

ES系列之Logstash實戰入門

概述 作為ELK技術棧一員&#xff0c;Logstash用于將數據采集到ES&#xff0c;通過簡單配置就能把各種外部數據采集到索引中進行保存&#xff0c;可提高數據采集的效率。 原理 數據源提供的數據進入Logstash的管道后需要經過3個階段&#xff1a; input&#xff1a;負責抽取數…

C#單向鏈表實現:在當前節點后插入新數據的方法Insert()

目錄 一、涉及到的知識點 1.插入算法 2.示例中current 和 _current 的作用 3.current 和 _current 能否合并為一個變量 4.單向鏈表節點類的三個屬性 &#xff08;1&#xff09;Next屬性&#xff1a; &#xff08;2&#xff09; Value屬性&#xff1a; &#xff08;3&am…

【ArcPy】批量讀取文件夾excel中XY并轉為點shp

示例展示 代碼 只讀取excel中含有XY字段的文件&#xff0c;并將矢量命名為excel文件名稱。 import os import pandas as pd import arcpy folder_path r"C:\Users\admin\Desktop\excelfile" extension"xlsx" files [file for file in os.listdir(folder…

SpringCloud gateway限流無效,redis版本低的問題

在使用springCloud gateway的限流功能的時候&#xff0c;配置RedisRateLimiter限流無效&#xff0c;后來發現是Redis版本過低導致的問題&#xff0c;實測 Redis版本為3.0.504時限流無效&#xff0c;改用7.0.x版本的Redis后限流生效。查了資料發現很多人都遇見過這個問題&#x…

RedisTemplate 序列化成功,反序列化失敗List, Set, Map失敗

RedisTemplate 序列化成功&#xff0c;反序列化失敗List, Set, Map失敗 異常信息RedisTemplate配置異常原因錯誤代碼示例解決方法 序列化成功&#xff0c;反序列化失敗 異常信息 Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve ty…

小程序事件處理

事件處理 一個應用僅僅只有界面展示是不夠的&#xff0c;還需要和用戶做交互&#xff0c;例如&#xff1a;響應用戶的點擊、獲取用戶輸入的值等等&#xff0c;在小程序里邊&#xff0c;我們就通過編寫 JS 腳本文件來處理用戶的操作 1. 事件綁定和事件對象 小程序中綁定事件與…

React之組件定義和事件處理

一、組件的分類 在react中&#xff0c;組件分為函數組件和class組件&#xff0c;也就是無狀態組件和有狀態組件。 * 更過時候我們應該區別使用無狀態組件&#xff0c;因為如果有狀態組件會觸發生命周期所對應的一些函數 * 一旦觸發他生命周期的函數&#xff0c;它就會影響當前項…

如何設置從小程序跳轉到其它小程序

?有的商家有多個小程序&#xff0c;希望能夠通過一個小程序鏈接到所有其它小程序&#xff0c;用戶可以通過點擊跳轉鏈接實現從一個小程序跳轉到另一個小程序。要怎么才能實現這樣的跳轉呢。下面具體介紹。 1. 設置跳轉。在小程序管理員后臺->分類管理&#xff0c;添加一個…

ssm個人學習01

Spring配置文件: spring環境的搭建: 1:導入對應的spring坐標 也就是依賴 2:編寫controller, service, dao相關的代碼 3:創建配置文件(在resource下面配置文件) 例如:applicationContext.xml <bean id "" class ""> <property name "&…

Node.js 中 fs 模塊文件操作的應用教程

Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運行環境&#xff0c;它可以讓 JavaScript 代碼在服務器端運行。在 Node.js 中&#xff0c;fs 模塊是用來處理文件系統操作的模塊。通過 fs 模塊&#xff0c;我們可以進行文件的讀取、寫入、刪除等操作。本教程將介紹如何在 No…

工作電壓范圍寬的國產音頻限幅器D2761用于藍牙音箱,輸出噪聲最大僅-90dBV

近年來隨著相關技術的不斷提升&#xff0c;音箱也逐漸從傳統的音箱向智能音箱、無線音箱升級。同時在消費升級的背景下&#xff0c;智能音箱成為人們提升生活品質的方式之一。智能音箱是智能化和語音交互技術的產物&#xff0c;具有點歌、購物、控制智能家居設備等功能&#xf…

python水表識別圖像識別深度學習 CNN

python水表識別&#xff0c;圖像識別深度學習 CNN&#xff0c;Opencv,Keras 重點&#xff1a;項目和文檔是本人近期原創所作&#xff01;程序可以將水表圖片里面的數據進行深度學習&#xff0c;提取相關信息訓練&#xff0c;lw1.3萬字重復15%&#xff0c;可以直接上交那種&…

Vue中<style scoped lang=“scss“>的含義

這段代碼中的<style scoped lang"scss">是HTML和Vue框架結合使用時常見的一個模式&#xff0c;具體含義如下&#xff1a; scoped&#xff1a;這是一個Vue.js特有的屬性&#xff0c;用來指定樣式只應用于當前組件的元素。沒有這個屬性時&#xff0c;樣式會全局應…

python給企微發消息

方法一&#xff1a;webhook方式。使用群機器人給企微群發消息 import requestsdef qwxsendmessage(msg):urlhttps://qyapi.weixin.qq.com/cgi-bin/webhook/send?key6c598840-804a-4eb5-a999-a023313 #url換成自己群機器人的webhookurldata{msgtype:text,text:{content:msg}}…

elasticsearch7.17 terms聚合性能提升90%+

背景 ES7 相比于 ES6 有多個層面的優化&#xff0c;對于開源的ES而言&#xff0c;升級是必經之路。 ES的使用場景非常多&#xff0c;在升級過程中可能會遇到非預期的結果&#xff1b; 比如之前文章提到的典型案例&#xff1a;ES7.17版本terms查詢性能問題 ES7.17版本terms查…