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 の間違い

推薦する

ftlcloud: 限定版 - 宣伝のためにお金を失っている、月額 9 元、ゴールド シールド + 天極防御、CC を無視、香港\韓国\米国のデータ センター

9元でどんなクラウドサーバーが買えますか? ftlcloud は自社の宣伝 (および市場獲得) を目...

簡単な説明: ウェブサイトのコンテンツを更新するときに注意すべき 2 つの量は何ですか?

高品質のコンテンツから高品質の Web サイトが生まれ、Web サイトのコンテンツの重要性は明らかで...

hostus-第 2 の香港 VPS レビュー/softlayer/1000M ポート

ここ 2 日間は忙しかったので、Hostus の香港 VPS のレビューを書くために戻ってきました。...

テンセントのオープンソースアプローチ:Apacheアプローチに基づくオープンソースの実践と探求

8月6日、テンセントオープンソースアライアンス会長兼テンセントクラウドオープンソースエコシステムゼネ...

Quora のランディング ページ最適化では、少ないほど効果的

有名な質疑応答ソーシャル ネットワーキング サイト Quora に次のような質問があります。 Quo...

支援者は2013年がOpenStackクラウド導入の年となることを期待している

クラウド コンピューティング市場にはいくつかの主要ベンダーがあり、Amazon Web Servic...

第9回ソフトコピーライティング&ソフトコピーマーケティング研修の申込受付を開始しました

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

インターネット上でウェブサイトを構築するのは複雑ではありません。鍵となるのは、5 つの「本質」を理解することです (パート 2)

前回の記事では、ドメイン名登録の安全性、適時性、適用性について主に説明しました。ウェブマスターがドメ...

Baiduの重量完全分析:ウェブサイトに高重量のショートカットを持たせる

ウェブサイトの重みを向上させることは、オンラインプロモーションの目標の1つです。サイトの最適化や更新...

無料申告に関するチャット:海外VPS無料申告推奨、無料申告クラウドサーバー

国内のVPS(クラウドサーバー)はすべて登録が必要です。責任を持って言いますが、登録が不要な国内のV...

誰もが雷鋒である——ソーシャルプラットフォームがユーザーエンゲージメントを向上させる方法

多くのソーシャル プラットフォーム開発者は、ポイント、レベル、リーダーボードなどのゲームのようなメカ...

PCとモバイル端末は統合されるべき。QQ Spaceがモバイルコミュニティ製品にもたらす4つの大きなインスピレーション

メーデー連休最終日の正午、QQ Spaceチームは「5月2日だけで、QQ Spaceにアップロードさ...

SEO初心者にスパムサイトと通常サイトの選び方を教える

スパムサイトを構築するか、通常のサイトを構築するかは、SEO 界では永遠の話題です。初心者はゴミステ...

曲頭条にはまだ突破のチャンスはあるのだろうか?

Qutoutiao は、新しい形式の情報閲覧を創造することに特化したソフトウェアです。モバイル アプ...

SEO初心者へ: SEOのストーリー

ウェブサイトの SEO に関して、多くの初心者はインターネットで関連情報を無目的に検索します。この人...