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

推薦する

2022年のテクノロジートレンド: デジタルトランスフォーメーション、クラウドコンピューティング、人材獲得競争

年末から来年の初めにかけて、研究機関や業界の専門家は、今後 1 年間のソフトウェア エコシステムの発...

オーディオポルノ鑑定士は毎日少なくとも4,000人の音声を聞いており、吐き気を催すほどだ

月給5,000~50,000のこれらのプロジェクトはあなたの将来ですA5 Entrepreneurs...

iONcloud/krypt クラウド サーバー: 長期 20% 割引クーポン、月額 6 ドルから、ロサンゼルス/サンノゼ/ホノルル/ダラス

Krypt のクラウド サーバー ブランドである ion では割引プロモーションが頻繁に行われており...

美麗碩と莫口街のブランドワード戦略の分析

みなさんこんにちは。私は徐子宇です。過去1年間、MeilishuoとMogujieがあまりにも多く私...

クラウド アーキテクト - クラウド コンピューティングの導入を成功させる上で重要な役割

クラウド戦略の重要性と複雑さが増すにつれて、クラウド アーキテクトは企業がリスクを回避し、クラウドへ...

Green Radish Algorithm 2.0 が登場、SEO で外部リンクを改善する方法

今年、Baidu は Green Radish Algorithm 1.0 をリリースし、最近 Gr...

事例分析:ブラックリストに登録されたウェブサイトの分析プロセス

ウェブマスターツール tool.chinaz.com の「ウェブサイトハッキング検出」でウェブサイト...

ウェブマスターネットワークからの毎日のレポート:百度が年間検索ランキングを発表、KubaとGomeが合併

1. 百度が2012年の年間検索ランキングを発表百度は2012年の年間検索チャートを発表した(htt...

NeoSurgeの簡単な紹介

Neosurge は、2002 年から 10 年以上の歴史を持つ小規模な IDC 企業です。社長の ...

InterServer-99 USD/E3-1230/16G メモリ/2X2t ハードディスク (raid1)/10T トラフィック/5IP

InterServer は、アメリカのホスティング会社として定評があります。1999 年に設立されま...

30 日間のサークル オブ フレンズ マーケティング: 始めるのは簡単ですが、続けるのは難しいです。

9月12日に「WeChatモーメントマーケティングの5日間の実践ノ​​ート」という記事を書きました。...

Redisson 分散ロック ソースコード 1: 再入可能ロック

[[407548]]序文誰もが分散サービスを使用しているため、分散サービスでの同時データ更新の問題は...

まだ意味のない外部リンクを作成していますか?

最近、多くの友人が、外部リンクの構築を主張する多くのウェブサイトのランキングが実際に下がり、中にはB...

SEM入札の基礎知識と事前準備とは?

暇な時に、過去数年間の入札経験について簡単にお話しし、皆さんと共有したいと思います。まずフローチャー...