banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

【転載】gRPCクイックスタート

title: 【転載】gRPC 快速入門
date: 2021-08-09 16:36:33
comment: false
toc: true
category:

  • Golang
  • gRPC
    tags:
  • 転載
  • Go
  • gRPC
  • クイック
  • 入門

本文転載自:gRPC 快速入門 | 李文周のブログ


RPC は近年比較的注目されている概念で、マイクロサービスアーキテクチャの台頭に伴い、RPC の応用がますます広がっています。本記事では RPC と gRPC の関連概念を紹介し、詳細なコード例を通じて gRPC の基本的な使用法を説明します。

gRPC#

RPC とは#

分散コンピューティングにおいて、リモートプロシージャコール(英語:Remote Procedure Call、略称 RPC)はコンピュータ通信プロトコルです。このプロトコルは、あるコンピュータ上で実行されているプログラムが、別のアドレス空間(通常はオープンネットワーク上のコンピュータ)のサブルーチンを呼び出すことを許可します。プログラマーは、ローカルプログラムを呼び出すのと同じように、追加のプログラミングを行うことなく(詳細に気を配る必要はありません)、この相互作用を行うことができます。RPC はサーバー - クライアント(Client/Server)モデルであり、古典的な実装は「リクエストを送信し、応答を受け取る」ことで情報を交換するシステムです。

gRPC とは#

gRPCは、任意の環境で実行できる現代的なオープンソースの高性能 RPC フレームワークで、最初は Google によって開発されました。HTTP/2 をトランスポートプロトコルとして使用します。

gRPC では、クライアントはローカルメソッドを呼び出すように、他のマシン上のサーバーアプリケーションのメソッドを直接呼び出すことができ、分散アプリケーションやサービスをより簡単に作成するのに役立ちます。多くの RPC システムと同様に、gRPC はサービスを定義し、パラメータと戻り値の型を持つリモート呼び出し可能なメソッドを指定することに基づいています。サーバープログラムでこのインターフェースを実装し、gRPC サービスを実行してクライアントの呼び出しを処理します。クライアントには、サーバーと同じメソッドを提供するスタブがあります。

image

なぜ gRPC を使うのか#

gRPC を使用することで、1 つの .protoファイルでサービスを定義し、それをサポートする任意の言語でクライアントとサーバーを実装できます。逆に、それらはさまざまなシナリオで使用でき、Google のサーバーからあなた自身のタブレットまで、gRPC は異なる言語や環境間の通信の複雑さを解決します。protocol buffersを使用することで、効率的なシリアル化、シンプルな IDL、インターフェースの更新の容易さなど、他の利点も得られます。要するに、gRPC を使用することで、私たちは言語を超えた分散コードをより簡単に書くことができます。

gRPC のインストール#

gRPC のインストール#

go get -u google.golang.org/grpc  

Protocol Buffers v3 のインストール#

gRPC サービスコードを生成するためのプロトコルコンパイラをインストールします。最も簡単な方法は、以下のリンクからあなたのプラットフォームに適した事前コンパイルされたバイナリファイル(protoc-<version>-<platform>.zip)をダウンロードすることです:https://github.com/google/protobuf/releases

ダウンロードが完了したら、以下の手順を実行します:

  1. ダウンロードしたファイルを解凍します
  2. protocバイナリファイルのパスを環境変数に追加します

次に、以下のコマンドを実行して protoc の Go プラグインをインストールします:

go get -u github.com/golang/protobuf/protoc-gen-go  

コンパイラプラグイン protoc-gen-go$GOBINにインストールされ、デフォルトでは $GOPATH/binです。これがあなたの $PATHに含まれている必要があります。そうしないと、プロトコルコンパイラ protocがそれを見つけることができません。

インストールの指定#

gRPC 開発は三つのステップに分かれます#

象を冷蔵庫に入れるのは何ステップですか?

  1. 冷蔵庫の扉を開けます。
  2. 象を入れます。
  3. 冷蔵庫の扉を閉めます。

gRPC 開発も同様に三つのステップに分かれます:

  1. .protoファイルを作成し、指定された言語のソースコードを生成します。
  2. サーバーコードを作成します
  3. クライアントコードを作成します

gRPC 入門例#

proto コードの作成#

gRPC は Protocol Buffers に基づいています。

Protocol Buffersは、言語に依存せず、プラットフォームに依存しない拡張可能なメカニズムで、構造化データをシリアル化するために使用されます。Protocol Buffersを使用すると、構造化データを一度定義し、特別に生成されたソースコードを使用して、さまざまなデータストリームでさまざまな言語で構造化データを簡単に読み書きできます。

Protocol Buffersに関するチュートリアルは、オンラインで検索できます。本記事では、読者が Protocol Buffersに精通していることを前提としています。

syntax = "proto3"; // バージョン宣言、Protocol Buffers v3を使用  

package pb; // パッケージ名  

// 挨拶サービスを定義  
service Greeter {  
    // SayHello メソッド  
    rpc SayHello (HelloRequest) returns (HelloReply) {}  
}  

// 名前を含むリクエストメッセージ  
message HelloRequest {  
    string name = 1;  
}  

// 挨拶文を含むレスポンスメッセージ  
message HelloReply {  
    string message = 1;  
}  

以下のコマンドを実行して、Go 言語のソースコードを生成します:

protoc -I helloworld/ helloworld/pb/helloworld.proto --go_out=plugins=grpc:helloworld  

gRPC_demo/helloworld/pbディレクトリに helloworld.pb.goファイルが生成されます。

サーバー側の Go コードの作成#

package main  

import (  
    "fmt"  
    "net"  

    pb "gRPC_demo/helloworld/pb"  
    "golang.org/x/net/context"  
    "google.golang.org/grpc"  
    "google.golang.org/grpc/reflection"  
)  

type server struct{}  

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {  
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil  
}  

func main() {  
    // ローカルの8972ポートをリッスン  
    lis, err := net.Listen("tcp", ":8972")  
    if err != nil {  
        fmt.Printf("failed to listen: %v", err)  
        return  
    }  
    s := grpc.NewServer() // gRPCサーバーを作成  
    pb.RegisterGreeterServer(s, &server{}) // gRPCサーバーにサービスを登録  

    reflection.Register(s) // 指定されたgRPCサーバーにサーバーリフレクションサービスを登録  
    // Serveメソッドはlisで受信接続を受け入れ、各接続のためにServerTransportとserverのgoroutineを作成します。  
    // このgoroutineはgRPCリクエストを読み取り、登録されたハンドラーを呼び出して応答します。  
    err = s.Serve(lis)  
    if err != nil {  
        fmt.Printf("failed to serve: %v", err)  
        return  
    }  
}  

上記のコードを gRPC_demo/helloworld/server/server.goファイルに保存し、コンパイルして実行します:

cd helloworld/server  
go build  
./server  

クライアント側の Go コードの作成#

package main  

import (  
    "context"  
    "fmt"  

    pb "gRPC_demo/helloworld/pb"  
    "google.golang.org/grpc"  
)  

func main() {  
    // サーバーに接続  
    conn, err := grpc.Dial(":8972", grpc.WithInsecure())  
    if err != nil {  
        fmt.Printf("faild to connect: %v", err)  
    }  
    defer conn.Close()  

    c := pb.NewGreeterClient(conn)  
    // サーバーのSayHelloを呼び出す  
    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "q1mi"})  
    if err != nil {  
        fmt.Printf("could not greet: %v", err)  
    }  
    fmt.Printf("Greeting: %s !\n", r.Message)  
}  

上記のコードを gRPC_demo/helloworld/client/client.goファイルに保存し、コンパイルして実行します:

cd helloworld/client/  
go build  
./client  

出力は以下のようになります(注意:サーバー側を先に起動してからクライアント側を起動してください):

$ ./client  
Greeting: Hello q1mi!  

この時点で、私たちのディレクトリ構造は以下のようになります:

./gRPC_demo  
├── go.mod  
├── go.sum  
└── helloworld  
    ├── client  
   ├── client  
   └── client.go  
   ├── client.py  
    ├── pb  
   ├── helloworld.pb.go  
   └── helloworld.proto  
    └── server  
        ├── server  
        └── server.go  

gRPC の言語間呼び出し#

次に、gRPC を使用して言語間の RPC 呼び出しを実現する方法を示します。

Python 言語を使用してクライアントを作成し、上記で Go 言語で作成したサーバーに RPC リクエストを送信します。

Python コードの生成#

gRPC_demoディレクトリで以下のコマンドを実行します:

python -m grpc_tools.protoc -I helloworld/pb/ --python_out=helloworld/client/ --grpc_python_out=helloworld/client/ helloworld/pb/helloworld.proto  

上記のコマンドは、gRPC_demo/helloworld/client/ディレクトリに以下の 2 つの Python ファイルを生成します:

helloworld_pb2.py  
helloworld_pb2_grpc.py  

Python 版クライアントの作成#

gRPC_demo/helloworld/client/ディレクトリに client.pyファイルを作成し、その内容は以下の通りです:

# coding=utf-8  

import logging  

import grpc  

import helloworld_pb2  
import helloworld_pb2_grpc  

def run():  
    # 注意(gRPC Python Team): .close()メソッドはchannelで使用可能です。  
    # そして、with文がコードの要件に合わない場合に使用するべきです。  
    with grpc.insecure_channel('localhost:8972') as channel:  
        stub = helloworld_pb2_grpc.GreeterStub(channel)  
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='q1mi'))  
    print("Greeter client received: {}!".format(response.message))  

if __name__ == '__main__':  
    logging.basicConfig()  
    run()  

上記のコードを保存して実行すると、出力結果は以下のようになります:

gRPC_demo $ python helloworld/client/client.py  
Greeter client received: Hello q1mi!  

これで、Python コードで作成したクライアントが Go 言語版のサーバーを呼び出すことができました。

右側のリンクをクリックして完全なコードを確認してください:gRPC_demo 完全コード

gRPC にはさらに多くの高度な使用法があります。未完待続…

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。