5 分で gRPC を学びましょう。学びましたか?

5 分で gRPC を学びましょう。学びましたか?

導入

長い間 Java を使ってきた開発者のほとんどは、gRPC に触れることはほとんどないと思います。結局のところ、Java 界隈で使用されているサービス フレームワークのほとんどは Dubbo/SpringClound です。

私も最近、ビジネスをゼロから再構築する機会があり、gRPC と出会いました。 gRPC を選択した理由はいくつかあります。

  • gRPC がほぼ標準的な通信プロトコルであるクラウドネイティブのアイデアに基づいてプロジェクトを開発および展開します。
  • 開発言語として Go が選択されましたが、Go コミュニティでは gRPC の方が明らかに優れた選択肢です。
  • 社内業務の一部はPythonで開発されており、gRPCは多言語対応が非常に優れています。

オンラインで 1 年以上安定して運用されてきた結果、gRPC は依然として非常に安定しており、効率的であることがわかります。 rpc フレームワークの中核となるポイントは次のとおりです。

  • シリアル化
  • 通信プロトコル
  • IDL (インターフェース記述言語)

これらは以下に対応します:

  • Protocol Buffer シリアル化プロトコルに基づいており、高いパフォーマンスを備えています。
  • HTTP/2標準プロトコルをベースに開発されており、ストリームや多重化などの機能が組み込まれています。同時に、標準プロトコルであるため、サードパーティツール(負荷分散、監視など)との互換性が向上します
  • .proto インターフェース ファイルを作成することで、共通言語コードを生成できます。

HTTP/2

gRPC を学習する前に、まず gRPC がどのようなプロトコルを介して通信するかを知っておく必要があります。私たちの日常的な開発やアプリケーションでは、基本的に HTTP/1.1 プロトコルに最も多く触れます。

HTTP/1.1 はテキスト プロトコルであるため、人間にとっては非常に使いやすいですが、マシン上でのパフォーマンスは比較的低くなります。

テキストを繰り返し解析する必要があるため、効率は当然低くなります。よりマシンフレンドリーにするにはバイナリを使用する必要がありますが、これは HTTP/2 によって自然に実現されます。

他にも利点があります:

  • 多重化: メッセージは互いに影響を与えることなく並行して送受信できます
  • HPACK はヘッダースペースを節約し、HTTP1.1 が同じヘッダーを繰り返し送信するのを防ぎます。

プロトコル

gRPC は、gRPC より前にリリースされたプロトコル シリアル化を使用します。したがって、gRPC だけでなく、シリアル化された IO 操作を必要とするあらゆるシナリオで使用できます。

より省スペースで高性能になります。 https://github.com/crossoverJie/cim の開発時にデータのやり取りに使用されました。

パッケージ順序.v1 ;

サービス OrderService {

rpc Create ( OrderApiCreate )( Order )を返します{ }

rpc Close ( CloseApiCreate )( Order )を返します{ }

//サーバープッシュ
rpc ServerStream ( OrderApiCreate )( stream Order )を返します{ }

//クライアントプッシュ
rpc ClientStream (ストリーム OrderApiCreate )( Order )を返します{ }

//双方向プッシュ
rpc BdStream (ストリーム OrderApiCreate )(ストリームOrder )を返します{ }
}

メッセージ OrderApiCreate {
int64 オーダーID = 1 ;
繰り返し int64 user_id = 2 ;
文字列コメント= 3 ;
繰り返し int32 reason_id = 4 ;
}

使い方も非常に簡単です。独自の .proto ファイルを定義するだけで、コマンドライン ツールを使用して対応する言語の SDK を生成できます。

詳細については、公式ドキュメントを参照してください: https://grpc.io/docs/languages/go/generated-code/

電話

 プロトコル--go_out=。 --go_opt=パス=ソース相対\
--go-grpc_out= を指定します。 --go-grpc_opt=パス=ソース相対\
テスト.proto

コードが生成されると、サーバーの作成は非常に簡単になります。生成されたインターフェースを実装するだけで済みます。

 func ( o * Order ) Create ( ctx context .Context , in * v1 .OrderApiCreate ) ( * v1 .Order , error ) {
//メタデータを取得
md ok : =メタデータ.FromIncomingContext ( ctx )
もしわかりました{
nil ステータス.Errorf (コード.DataLoss "メタデータの取得に失敗しました" )を返します
}
fmt .Println ( md )
fmt .Println ( .OrderId )
戻り値& v1 .Order {
OrderId : .OrderId
理由:なし
} ゼロ
}

クライアントも非常にシンプルで、サーバー コードに依存して接続を作成し、ローカル メソッドを呼び出すだけです。

これは、1 つのリクエストが 1 つのレスポンスに対応する、http のリクエスト/レスポンス モデルに似た、典型的な単項呼び出しです。

サーバーストリーム

gRPC は、通常の単項呼び出しに加えて、特定のシナリオで非常に便利なサーバー プッシュもサポートしています。

 func ( o * Order ) ServerStream ( in * v1 .OrderApiCreate , rs v1 .OrderService_ServerStreamServer )エラー{
i : = 0の場合;< 5 ;私は++ {
rs .Send ( & v1 .Order {
OrderId : .OrderId
理由:なし
}
}
ゼロを返す
}

サーバーのプッシュ機能は上記に示されています。プッシュ関数を呼び出してクライアントにプッシュすることができます。

 のために{
メッセージエラー: = rpc.RecvMsg ( )
err == io.EOFの場合{
marshalIndent , _ : = json .MarshalIndent ( msgs , "" , "\t" )
fmt .Println (メッセージ)
戻る
}
}

クライアントは、ループ内で現在受信されているデータ パケットが終了したかどうかを判定することによって、サーバー メッセージを取得します。

このプロセスをより直感的に示すために、以前に開発された gRPC クライアントが、ストリーム呼び出しを直感的にデバッグできるように最適化されました。

上の図はサーバープッシュの例です。

クライアントストリーム

サーバー プッシュのサポートに加えて、クライアントもそれをサポートします。

クライアントは同じ接続でサーバーにデータを送信し続け、サーバーはメッセージを並行して処理できます。

 //サーバーコード
func ( o * Order ) ClientStream ( rs v1 .OrderService_ClientStreamServer )エラー{
var 値[ ] int64
のために{
受信,エラー: = rs .受信( )
err == io.EOFの場合{
rs .SendAndClose ( & v1 .Order {
注文ID : 100
理由:なし
}
log .Println ()
ゼロを返す
}
value = append ( recv.OrderId )
log .Printf ( "ClientStream 受信メッセージ %v" recv .OrderId )
}
log .Println ( "ClientStream 終了" )
ゼロを返す
}

//クライアントコード
i : = 0の場合;< 5 ;私は++ {
メッセージ _ : = GetMsg (データ)
rpc .SendMsg (メッセージ[ 0 ] )
}
受信エラー: = rpc.CloseAndReceive ( )

コードはサーバー プッシュに似ていますが、役割が入れ替わります。

双方向ストリーム

同様に、クライアントとサーバーの両方が同時にメッセージを送信する場合もサポートされます。

 //サーバー
func ( o * Order ) BdStream ( rs v1 .OrderService_BdStreamServer )エラー{
var 値[ ] int64
のために{
受信,エラー: = rs .受信( )
err == io.EOFの場合{
log .Println ()
ゼロを返す
}
err != nil の場合{
パニックエラー
}
value = append ( recv.OrderId )
log .Printf ( "BdStream 受信メッセージ %v" recv .OrderId )
rs .SendMsg ( & v1 .Order {
注文ID :受信.注文ID
理由:なし
}
}
ゼロを返す
}
//クライアント
i : = 0の場合;< 5 ;私は++ {
メッセージ _ : = GetMsg (データ)
//メッセージを送信する
rpc .SendMsg (メッセージ[ 0 ] )
//メッセージを受信する
受信 _ : = rpc.RecvMsg ( )
marshalIndent , _ : = json .MarshalIndent (受信, "" , "\t" )
fmt .Println (文字列( marshalIndent ) )
}
rpc.CloseSend ( ) 関数

実際のところ、それは単に 2 つの訴えを 1 つに組み合わせただけです。

例を挙げるとわかりやすいです。

メタデータ

gRPC は、HTTP のヘッダーと同様に、メタデータの送信もサポートしています。

 //クライアントが書き込み
metaStr : = ` { "lang" : "zh" } `
var m map [文字列]文字列
err : = json .Unmarshal ( [ ] byte ( metaStr ) , & m )
md : =メタデータ。新着( m )
//呼び出すときにctxを渡すだけです
ctx : =メタデータ.NewOutgoingContext (コンテキスト.Background ( ) , md )

//サーバーは受信
md ok : =メタデータ.FromIncomingContext ( ctx )
もしわかりました{
nil ステータス.Errorf (コード.DataLoss "メタデータの取得に失敗しました" )を返します
}
fmt .Println ( md )

gRPC ゲートウェイ

gRPC は強力で使いやすいですが、ブラウザやアプリのサポートは REST ほど広まっていません (ブラウザもサポートしていますが、アプリケーションは非常に少ないです)。

この目的のために、コミュニティは https://github.com/grpc-ecosystem/grpc-gateway プロジェクトを作成しました。このプロジェクトでは、gRPC サービスを RESTFUL API として公開できます。

テスターがインターフェース テストに postman を使用することに慣れるために、より便利なテストのために gRPC サービスもプロキシします。

リフレクションコール

RPC フレームワークとして、サポート ツールの開発を容易にするために、一般化された呼び出しもサポートする必要があります。 gRPC はリフレクションを通じてサポートされており、サービス名と pb ファイルを取得することでリフレクション呼び出しが行われます。

https://github.com/jhump/protoreflect このライブラリは、一般的なリフレクション操作をカプセル化します。

上の図に示されている視覚化ストリーム呼び出しも、このライブラリを通じて実装されています。

負荷分散

gRPC は HTTP/2 に基づいて実装されているため、クライアントとサーバーは長時間の接続を維持します。負荷分散は HTTP ほど単純ではありません。

接続ではなくリクエストの負荷分散を必要とする gRPC を使用して、HTTP と同じ効果を実現したいと考えています。

通常、2 つのアプローチがあります。

  • クライアント負荷分散
  • サーバー側の負荷分散

クライアント負荷分散は、RPC 呼び出しで広く使用されています。たとえば、Dubbo はクライアント負荷分散を使用します。

gRPC は関連するインターフェースも提供します。詳細については公式デモを参照してください。

https://github.com/grpc/grpc-go/blob/87eb5b7502/examples/features/load_balancing/README.md

クライアント側の負荷分散は開発者にとって比較的柔軟性が高く (独自の戦略をカスタマイズできます)、開発者自身でロジックを維持する必要もあります。複数の言語がある場合は、複数のコピーを維持する必要があります。

したがって、クラウド ネイティブの一般的なテーマでは、サーバー側の負荷分散を使用することがより推奨されます。

オプションは次のとおりです:

  • イスティオ
  • 特使
  • アピックス

私たちもこの分野を研究しており、おそらく envoy/istio を使用する予定です。

要約する

gRPC にはまだ多くのコンテンツがあります。この記事は、gRPC を知らない人に基本的な理解を与えることを目的とした入門文書です。これはまさにクラウドネイティブ時代に必要なスキルです。

この記事の gRPC クライアントに興味のある方は、ここのソース コードを参照してください: https://github.com/crossoverJie/ptg。

<<:  Tektonシリーズに関する理論的な記事

>>:  Kubernetes で絶対にしてはいけない 10 の間違い

推薦する

出典を明記せずに原著論文が転載された場合、自分が原著者であることを証明するにはどうすればよいでしょうか?

我が国は知的財産権の保護が比較的弱い国です。まさにこのため、イノベーションへの道が閉ざされています。...

パフォーマンスが2倍になります! Cloud Native GatewayはTLSハードウェアアクセラレーションをサポート

ネットワーク環境がますます複雑になるにつれて、従来の HTTP プレーンテキスト伝送プロトコルによっ...

ソースコードホスティングサイトGitHubが初の外部資金で1億ドルを調達

フェニックステクノロジーニュース、北京時間7月10日、海外テクノロジーブログgigaomによると、米...

A5 Webmaster Networkの第8回ソフトコピーライティングとソフトコピーマーケティングトレーニングの申し込み受付を開始しました

企業向けでもウェブサイトマーケティング向けでも、ソフトテキストマーケティングは欠かせないマーケティン...

6月の第1週、DNSPodはシェア1.17%で9位にランクされました。

IDC Review Network (idcps.com) は 6 月 16 日に次のように報告し...

天一雲、あなたの妹よ!

私はMumaoから1GメモリのTianyi Cloudを購入しました。年間払いの場合、プロモーション...

virpus-XEN 6か月間50%オフ(シンプルデータ付き)

virpus VPS については投稿するつもりはなかったのですが、グループ内の何人かがまだそれについ...

引き続き李佳琦氏を招待します。流行中の電子商取引のライブストリーミングはどれほど熱狂的ですか?

李佳琦は昨年12月に高徳地図のナビゲーションを録音し、ネットユーザーから「Keepの音声を早くリリー...

kvmla: 日本/香港/シンガポール、VPS 直接 20% オフ (+ 再チャージ 20% 以上)、専用サーバー 25% オフ (初月 300 元オフ)

定評のあるホスティング プロバイダーである kvmla は、リピーターのユーザー向けに VPS と専...

コンテンツの模倣は有害であり、重量を減らすことが唯一の解決策です

最近、百度Kステーションは活発に活動しており、多くのウェブマスターが罠にかかっています。一方では、百...

Huawei GaussDBデータベースは、コア金融インテリジェント生産および取引ソリューションを作成するためのデュアル分散アーキテクチャを導入

2019年グローバルデータインフラストラクチャフォーラム金融サミットにおいて、ファーウェイはGaus...

SEO ではトラフィックとコンバージョン率のどちらがより重要ですか?

SEO ではトラフィックとコンバージョン率のどちらが重要ですか? この問題は、ウェブマスターの間で長...

Baidu Search が Aurora アルゴリズムを発表、ランディング ページの時間の標準化に注目

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています2018 ...

ウェブサイトのコンテンツ構造に関する考察

ウェブサイト、機能。ウェブサイトに機能が 1 つもないとしたら、どうやってユーザーを維持できるでしょ...

buyvm 大きな変更 データセンターの利用規約の変更

buyvm は低価格 VPS の代表です。中国人は buyvm のサンノゼ データ センターの VP...