[マイクロサービスランディング]サービス間の通信:gRPCの概要

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バージョンに一貫性がありません。初めて使用する場合は、最新バージョンを使用し、常にこのバージョンを使用してください。または、最新バージョンに変更してコードファイルを再生成します。

他にご不明な点がございましたら、コメントしてください。更新させていただきます。

おすすめ

転載: blog.csdn.net/happy_teemo/article/details/113430428