gRPCとは
公式紹介:
https ://grpc.io/docs/what-is-grpc/introduction/
「高性能のオープンソースユニバーサルRPCフレームワーク」
- 多言語:言語中立、複数の言語をサポートします。
- 軽量で高性能:シリアル化はPB(プロトコルバッファ)とJSONをサポートします。PBは言語に依存しない高性能シリアル化フレームワークです。
- IDL:ファイルに基づいてサービスを定義し、proto3ツールを使用して、指定された言語のデータ構造、サーバーインターフェイス、およびクライアントスタブを生成します。
- デザインのコンセプト
- モバイル端末:標準のHTTP2設計に基づいて、双方向ストリーミング、メッセージヘッダー圧縮、単一TCP多重化、サーバープッシュなどの機能をサポートします。これらの機能により、モバイルデバイスでのgRPCの省電力化とネットワークトラフィックの節約が実現します。
- オブジェクトの代わりにサービス、参照の代わりにメッセージ:マイクロサービスを促進するシステム間の粗粒度のメッセージ相互作用の設計概念。
- 負荷に依存しない:サービスが異なれば、プロトコルバッファ、JSON、XML、Thriftなどのさまざまなメッセージタイプとエンコーディングを使用する必要があります。
- 流:Streaming API。
- ブロッキングと非ブロッキング:クライアントとサーバー間で交換されるメッセージシーケンスの非同期および同期処理をサポートします。
- メタデータ交換:認証や追跡などの一般的な横断的関心事は、データ交換に依存しています。
- 標準化されたステータスコード:クライアントは通常、API呼び出しによって返されたエラーに限定的な方法で応答します。
概要
- grpcはプロトコルであり、protoファイルに対応します
- protobufはjrpcをコードに変換するツールです
インストール
grpcバッグ
go get -u google.golang.org/grpc
protobuf
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
protoc構文
- -Iパラメータ:インポートパスを指定します。複数の-Iパラメータを指定できます。コンパイル時に順番に検索します。指定しない場合は、デフォルトで現在のディレクトリが検索されます。
- –go_out:Golangコンパイルのサポート、次のパラメーターをサポート
- plugins = plugin1 + plugin2-プラグインを指定します。現在、grpcのみがサポートされています。つまり、plugins = grpc
- Mパラメーター-インポートされた.protoファイルのパスとコンパイル後の対応するgolangパッケージ名を指定します(このパラメーターが指定されていない場合、デフォルトは.protoファイル内のインポートステートメントのパスです)
- import_prefix = xxx-主にサブディレクトリ内の複数のprotoファイルをコンパイルするために使用されるすべてのインポートパスにプレフィックスを追加します。このパラメータはかなり便利で、場合によってはMパラメータを置き換えるのに特に適していますが、実際の使用には問題があります。期待した効果が得られないので、自分で確かめてみてください
- import_path = foo / bar-パッケージまたはgo_package宣言のないファイルのパッケージ名を指定するために使用されます。右端のスラッシュの前の文字は無視されます
- 終了:コンパイルされたファイルパス。プロトファイルパス(ワイルドカードをサポート)
protoc --go_out=. example.proto
protoc --go-grpc_out=. example.proto
デモ
https://gitee.com/HappyTeemo/grpc-demo.git
プロトファイル
syntax = "proto3";
# 定义了包名
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc 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;
}
生成
protoc --go_out=. helloworld.proto
protoc --go-grpc_out=. helloworld.proto
さらに2つのファイルがあります
サーバ
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
port = ":50051"
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{
Message: "Hello " + in.GetName()}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{
})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
注意
サーバーは実際にはプロトコルにインターフェースを実装すること、つまりすべてのメソッドを実装することです
type HelloServer interface {
// 定义SayHello方法
SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
mustEmbedUnimplementedHelloServer()
}
多くのチュートリアルはmustEmbedUnimplementedHelloServerメソッドを実装していますが、小文字であるため、同じディレクトリが適切であり、ディレクトリをまたぐと問題が発生します。
直接する必要があります:
type server struct {
pb.UnimplementedGreeterServer
}
クライアント
package main
import (
"context"
"log"
"os"
"time"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{
Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
共通のピット
- grpcバージョンとprotocバージョンに一貫性がありません。初めて使用する場合は、最新バージョンを使用し、常にこのバージョンを使用してください。または、最新バージョンに変更してコードファイルを再生成します。