46. GRPCの最初の知識-20:45:43、2020年4月12日

2020年4月12日19:38:25

GRPC初期

GRPCプロトコル(Googleリモートプロシージャコールプロトコル)はGoogleが提供するHTTP2プロトコルに基づく、高性能な汎用RPCオープンソースソフトウェアフレームワークです通信の両当事者はフレームワークに基づいて二次開発を実行するため、GRPCソフトウェアフレームワークによって実現される基本的な通信に注意を払うことなく、通信の両当事者がビジネスに集中できます。

公式ドキュメント:

http://doc.oschina.net/grpc?t=58011

GRPCプロトコルスタックの階層化を以下に示します。

図1-1 GRPCプロトコルスタックの階層化
img

表1-1 GRPCプロトコルスタックの階層化

野原 解説
TCPレイヤー 基礎となる通信プロトコルは、TCP接続に基づいています。
TLSレイヤー このレイヤーはオプションで、TLS 1.2暗号化チャネルと双方向証明書認証に基づいています。
HTTP2レイヤー GRPCはHTTP2プロトコルで実行され、双方向ストリーミング、フロー制御、ヘッダー圧縮、単一接続での多重化要求などのHTTP2の機能を利用します。
GRPCレイヤー リモートプロシージャコールは、リモートプロシージャコールのプロトコル対話形式を定義します。
データモデルレイヤー 通信の両方の当事者は、正しく対話するために、互いのデータモデルを理解する必要があります。

gRPCはHTTP / 2プロトコルに基づいています。gRPCを深く理解するには、HTTP / 2を理解する必要があります。ここでは、まずHTTP / 2に関する知識を簡単に紹介し、次にgRPCがHTTP / 2に基づいて構築される方法を紹介します。

HTTP / 1.x

この段階では、HTTPプロトコルはWebで最も一般的なプロトコルと見なすことができます。以前から、多くのアプリケーションはHTTP / 1.xプロトコルに基づいていました。HTTP/ 1.xプロトコルはテキストプロトコルであり、非常に読みやすくなっています。しかし、それはあまり効率的ではありません。

パーサー

完全なHTTPリクエストを解析する場合は、最初にHTTPヘッダーを正しく読み取ることができる必要があります。HTTPヘッダは、各使用するフィールド\r\n体間次いで、別々に\r\n\r\n分離しました。ヘッダを解析が完了した後、我々は内側からヘッダできるcontent-length体を読むように、身体のサイズを取得します。

コードの実装には次のような多くの最適化メソッドがありますが、完全なHTTPリクエストを解析するには何度も読み取る必要があるため、この一連のプロセスは実際には効率的ではありません。

  • 複数のIO読み取りを回避するために、一度に大きなデータブロックをバッファーに読み取ります。
  • 直接一致読んだ場合\r\n様式ストリーム解析を

ただし、高性能サービスの場合、上記の方法には依然としてオーバーヘッドがあります。実際、主な問題は、HTTP / 1.xプロトコルがテキストプロトコルであり、人間にやさしいということです。マシンに優しくしたい場合は、バイナリプロトコルの方が適しています。

HTTP / 1.xの解析に非常に興味がある場合は、非常に効率的でコンパクトなCライブラリであるhttp-parserを調べることができます。このライブラリを統合してHTTP / 1.xを処理する多くのフレームワークを見てきました。

リクエスト/レスポンス

HTTP / 1.xのもう1つの問題は、インタラクティブモードです。接続は一度に1つの質問しかできない、つまり、クライアントがリクエストを送信した後、次のリクエストを送信し続ける前に、応答を待つ必要があります。

このメカニズムは非常に単純ですが、ネットワーク接続の使用率が低くなります。多数のインタラクションが同時に必要な場合、クライアントはサーバーとの複数の接続を確立する必要がありますが、接続の確立にもオーバーヘッドがあるため、パフォーマンスのために、通常これらの接続は常に長い接続であり、サーバーは数百の同時接続を処理しますWan Connectは大きな課題ではありませんが、あまり効率的ではありません。

押す

プッシュにHTTP / 1.xを使用したことがある学生は、HTTP / 1.xにプッシュメカニズムがないため、どれほど辛いかを知っているでしょう。したがって、通常は2つの方法があります。

  • ロングポーリング方式。つまり、サーバーへの接続を直接停止し、一定時間(1分など)待機します。サーバーが戻るかタイムアウトになると、再度ポーリングします。
  • Webソケットは、アップグレードメカニズムを通じて、このHTTP接続を明示的に双方向の対話用のネイキッドTCPに変換します。

ロングポーリングと比較して、私は依然としてWebソケットを好みますが、結局のところ、それはより効率的ですが、Webソケットの背後にある対話は、従来の意味でのHTTPではありません。

こんにちはHTTP / 2

HTTP / 1.xプロトコルは現在インターネットで最も広く使用されているプロトコルである可能性がありますが、Webサービスの規模が拡大し続けるにつれて、HTTP / 1.xはますます不安定になり、より良いプロトコルの別のセットが緊急に必要です。サービスを作成して、HTTP / 2を作成します。

HTTP / 2はバイナリプロトコルです。つまり、その可読性はほぼ0ですが、幸いにも、Wiresharkなど、解析できるツールがたくさんあります。

HTTP / 2を理解する前に、いくつかの一般的な用語を知っておく必要があります。

  • ストリーム:双方向ストリーム。接続には複数のストリームを含めることができます。
  • メッセージ:これは上記の論理的な要求と応答です。
  • フレーム::データ転送の最小単位。各フレームは、特定のストリームまたは接続全体に属しています。メッセージは複数のフレームで構成される場合があります。

gRPCはもともとGoogleによって開発され、言語に依存せず、プラットフォームに依存しない、オープンソースのリモートプロシージャコール(RPC)システムです。

gRPCでは、クライアントアプリケーションがローカルオブジェクトのような別のマシン上のサーバーアプリケーションのメソッドを直接呼び出すことができるため、分散アプリケーションやサービスを簡単に作成できます。多くのRPCシステムと同様に、gRPCもサービスを定義し、リモートで呼び出すことができるメソッド(パラメーターと戻り値の型を含む)を指定するという概念に基づいています。このインターフェースをサーバーに実装し、gRPCサーバーを実行してクライアント呼び出しを処理します。クライアントにスタブがあると、サーバーのように振る舞うことができます。

ここに写真の説明を書きます

特徴

  • HTTP / 2に基づく
    HTTP / 2は、接続の多重化、双方向ストリーミング、サーバープッシュ、リクエストの優先度、ヘッダー圧縮、その他のメカニズムを提供します。帯域幅の節約、TCP接続の数の削減、CPUの節約、モバイルデバイスのバッテリ寿命の延長などを行うことができます。gRPCのプロトコル設計はHTTP2の既存のセマンティクスを使用し、リクエストとレスポンスのデータはHTTPボディを使用して送信され、その他の制御情報はヘッダーで表されます。
  • IDLは、ProtoBuf
    gRPCを使用して、ProtoBufを使用してサービスを定義します。ProtoBufは、Googleが開発したデータシリアライゼーションプロトコルです(XML、JSON、Hessianに類似しています)。ProtoBufはデータをシリアル化でき、データストレージおよび通信プロトコルで広く使用されています。高い圧縮効率と伝送効率、シンプルな構文、強力な表現力。
  • 多言語サポート(C、C ++、Python、PHP、Nodejs、C#、Objective-C、Golang、Java)
    gRPCは複数の言語をサポートし、言語に基づいてクライアントおよびサーバー関数ライブラリを自動的に生成できます。現在、Cバージョンgrpc、Javaバージョンgrpc-java、Goバージョンgrpc-goが提供されており、その他の言語バージョンも活発に開発されています。その中で、grpcはC、C ++、Node.js、Python、Ruby、Objective-C、PHPをサポートしています。また、C#、grpc-javaなどの言語はすでにAndroid開発をサポートしています。

gRPCはGoogleのクラウドサービスと外部提供のAPIで使用されています。主なアプリケーションシナリオは次のとおり
です
。-低レイテンシ、高いスケーラビリティ、分散システム-クラウドサーバーと通信するモバイルアプリケーションクライアント-
設計言語は独立していて効率的です、
認証、ロードバランシング、ロギング、モニタリングなど、拡張のすべての側面を容易にする正確な新しいプロトコルレイヤー構造の設計。

HTTP2.0の機能

ハイパーテキスト転送プロトコルの2番目のバージョンであるHTTP / 2は、1または2にかかわらず、メソッドのセマンティクス(GET / PUST / PUT / DELETE)、ステータスコード(200/404/500など)のHTTPの基本的なセマンティクスは変更されていません。など)、範囲要求、キャッシュ、認証、URLパス、主な違いは次のとおりです。

多重化

HTTP / 1.1プロトコルでは、「ブラウザクライアントは同じドメイン名に対して同時に一定数のリクエストを持っています。制限を超えるリクエストはブロックされます。」

HTTP / 2の多重化により、単一のHTTP / 2接続を介して複数の要求/応答メッセージを同時に開始できます。
したがって、HTTP / 2は、複数のTCP接続の確立に依存することなく、マルチストリームの並列処理を簡単に実現できます。HTTP/ 2は、HTTPプロトコル通信の基本単位を1つのフレームに削減し、これらのフレームは論理ストリーム内のメッセージに対応します。同じTCP接続で双方向にメッセージを並行して交換します。

ここに写真の説明を書きます

バイナリフレーム

HTTP / 2によって送信されるデータはバイナリです。HTTP / 1.1のプレーンテキストデータと比較すると、バイナリデータの明らかな利点は、伝送量が少ないことです。これは低負荷を意味します。バイナリフレームも解析が容易で、エラーが発生しにくくなります。スペース、大文字、空白行、改行を処理する場合は、プレーンテキストフレームも考慮する必要があります。バイナリフレームにはこの問題はありません。

ここに写真の説明を書きます

ヘッダー圧縮

HTTPはステートレスプロトコルです。つまり、これは、サーバーに前の要求のメタデータを保存させるのではなく、各要求がサーバーに必要なすべての詳細を伝える必要があることを意味します。http2はこのパラダイムを変更しないため、変更する必要もあります(すべての詳細を伝達する)。したがって、HTTPリクエストのヘッダーには、CookieなどのIDを識別するために使用されるデータを含める必要があり、これらのデータの量も時間とともに増加します。各リクエストのヘッダーには、これらの大量の重複データが含まれています。これは間違いなく大きな負担です。リクエストヘッダーを圧縮すると、この負担が大幅に軽減されます。特にモバイル端末の場合、パフォーマンスの向上は明らかです。

HTTP / 2で使用される圧縮方式はHPACKです。http://http2.github.io/http2-spec/compression.html

HTTP2.0は、クライアントとサーバーの「ヘッダーテーブル」を使用して、以前に送信されたキーと値のペアを追跡および保存します。同じデータの場合、各要求と応答を通じて送信されることはありません。通信中にほとんど変更されない共通キー-値のペア(ユーザーエージェント、受け入れ可能なメディアタイプなど)は、一度だけ送信する必要があります。

ここに写真の説明を書きます

実際、リクエストにヘッダーが含まれていない場合(同じリソースに対するポーリングリクエストなど)、ヘッダーのオーバーヘッドは0バイトです。このとき、すべてのヘッダーは、以前に送信を要求されたヘッダーを自動的に使用します。

ヘッダーが変更された場合、変更されたデータをヘッダーフレームで送信するだけでよく、新しく追加または変更されたヘッダーフレームが「ヘッダーテーブル」に追加されます。ヘッダーテーブルは常にHTTP2.0の接続期間中に存在し、クライアントとサーバーの両方によって徐々に更新されます。

サーバープッシュ

HTTP / 2サーバープッシュによって行われる処理は、サーバーがクライアントからリソースの要求を受信すると、クライアントがクライアントから要求する他のリソースを決定し、これらのリソースを一緒にクライアントに送信します。クライアント(これらのリソースが必要であるとクライアントが明示的に述べていない場合でも)

クライアントは、追加のリソースをキャッシュに入れるか(この機能はキャッシュプッシュとも呼ばれます)、またはRST_STREAMフレームを送信して不要なリソースを拒否することを選択できます。

ここに写真の説明を書きます

アクティブリセットリンク

Length HTTPメッセージが送信された後、それを中断することは困難です。もちろん、通常はTCP接続全体を切断できます(ただし常にではありません)が、その代償として、3ウェイハンドシェイクを介して新しいTCP接続を再確立する必要があります。

HTTP / 2はRST_STREAMフレームを導入して、クライアントが既存の接続でリセット要求を送信できるようにし、それによって応答を中断または破棄します。ブラウザーがページジャンプを実行するか、ユーザーがダウンロードをキャンセルすると、新しい接続の確立が妨げられ、すべての帯域幅の浪費を回避できます。

gRPCの長所と短所:

利点:

Protobufバイナリメッセージ、優れたパフォーマンス/高効率(スペースと時間の効率は非常に良い)
プロトファイルはターゲットコードを生成し、使いやすい
シリアライゼーションとデシリアライゼーションは、解析後のマッピングなしで、プログラムのデータクラスに直接対応します(XML、 JSONがすべての方法)
上位互換性(新しい追加フィールドはデフォルト値を使用)と下位互換性(新規追加フィールドを無視)を
サポートし、アップグレードを簡素化複数の言語をサポート(プロトファイルはIDLファイルと考えることができます)
Nettyおよびその他のフレームワーク統合

短所:

1)GRPCは接続プールを提供していないため、それ自体で実装する必要があります
。2)「サービスディスカバリ」および「ロードバランシング」のメカニズムは提供されていません
。3)HTTP2に基づいているため、ほとんどのHTTPサーバーとNginxはそれらのほとんどでサポートされていません。 HTTP要求としての、ただし通常のTCP要求としての負荷分散。(nginx1.9バージョンでサポートされています)
4)Protobufはバイナリの読みやすさが不十分です(Text_Fromat関数を提供しているようです)
デフォルトでは動的機能がありません(動的定義を通じてメッセージタイプを生成するか、動的コンパイルをサポートできます)

例:

gRPCは通常のTCPベースの実装とは異なり、HTTP2プロトコルに直接基づいています。HTTP2はgrpcをモバイルクライアントとサーバーの通信シナリオにより適したものにし、接続の多重化はRPCの効率も保証します。

gRPCプロトコルの設計では、HTTP2の既存のセマンティクスが非常によく使用されており、リクエストとレスポンスのデータはHTTPボディを使用して送信され、その他の制御情報はヘッダーで表されます。

最初に例を見て、Protobufが次のように定義されているとします。

package foo.bar;

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloResponse);
}

これで1つ定義しましたservice HelloServiceそのような呼び出しのためにgrpcによって送信される要求は次のとおりです。

HEADERS (flags = END_HEADERS)
:method = POST
:scheme = http
:path = /foo.bar.HelloService/SayHello
:authority = api.test.com
grpc-timeout = 1S
content-type = application/grpc+proto
grpc-encoding = gzip
authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v

DATA (flags = END_STREAM)
<Delimited Message>

Httpリクエストのパス部分は、呼び出されるサービスを示すために使用されます。形式は/{package}.{ServiceName}/{RpcMethodName}

content-type 現在の値はapplication/grpc+proto

将来、grpcがJsonなどのProtobuf以外のプロトコルをサポートする場合、他の値が存在するようになります。

grpc-encodinggzip, deflate, snappy 使用される圧縮方法を示す同じ値を持つことができます

grpc-timeout 通話のタイムアウト期間を単位で示しますHour(H), Minute(M), Second(S), Millisecond(m), Microsecond(u), Nanosecond(n)

grpcで定義されている標準ヘッダーに加えて、新しいヘッダーを自分で追加することもできます。それはバイナリヘッダーの場合は、Header Name -bin最後に、

Header Value Base64でエンコードされたバイナリデータです。

サーバーはこのリクエストに対する応答を返します。

HEADERS (flags = END_HEADERS)
:status = 200
grpc-encoding = gzip

DATA
<Delimited Message>

HEADERS (flags = END_STREAM, END_HEADERS)
grpc-status = 0 # OK
trace-proto-bin = jher831yy13JHy3hc

grpc-statusが0の場合、要求に問題はなく、正常に戻ります。

grpcはGOAWAYフレームも定義します。サーバーが接続を切断する場合、サーバーはそのようなメッセージをクライアントに送信する必要があります。PINGフレームは、PINGフレームを受信した後、接続の存続検出と遅延検出のために、データをそのまま直接返します。

HTTP2のヘッダーは特に効率的な形式ではなく、保存と解析にいくつかの効率の問題があります。暗号化された接続が有効になっている場合、効率のオーバーヘッドが増加します。

おすすめ

転載: www.cnblogs.com/oneapple/p/12687498.html