gRPCのサンプルを作って動かしてみた。

## gRPCとは？
仕事関係で、gRPC技術と関わっていたので、調べてみることにしました。

ググってみると、
「gRPCは、Googleが開発したオープンソースの高性能なリモートプロシージャコール（RPC）フレームワークです。」らしいです。

えーと、ぴんとこないので、ChatGPTに簡単に解析をお願いしました。

>質問: ちょっとわかりづらいので、小学生でもわかるようなケースを例をあげて欲しいです。

回答: 以下は回答です。
>
>もちろんです。gRPCを小学生に説明するなら、こんな感じでしょうか：
>
>想像してみてください。あなたは大きな学校の一部で、たくさんのクラスがあります。各クラスは、特別なタスク（仕事）を持っています。例えば、一つのクラスは図画を描くことが得意で、もう一つのクラスは音楽を作ることが得意です。
>
>でも、時々、あるクラスが別のクラスの助けを必要とすることがあります。音楽クラスが絵を描くことが必要になった時、どうすればいいでしょう？そこで、gRPCというシステムが活躍します。
>
>gRPCは、学校の中でメッセージを送るための超速いポストマンのようなものです。音楽クラスが絵を描いてほしい時、gRPCポストマンにメッセージを渡します。そして、gRPCポストマンはそのメッセージを超速で図画クラスに届けます。図画クラスはそのメッセージを受>け取り、必要な絵を描いて、またgRPCポストマンを使って音楽クラスに戻します。
>
>このシステムが素晴らしいのは、どのクラスも特別な言葉（プログラミング言語）を使って話すことができ、gRPCポストマンはそれら全ての言葉を理解して、クラス間で正確にメッセージを届けることができる点です。
>
>更に、gRPCポストマンはとても安全にメッセージを運ぶことができるので、誰かにメッセージが盗まれる心配はありません。そして、一度にたくさんのメッセージを運ぶことができるので、とても効率的です。
>
>だから、学校（システム）がたくさんのクラス（サービス）で成り立っていて、お互いに助け合いながら素晴らしいプロジェクト（アプリケーション）を作りたい時、gRPCはとても役に立ちます。

なるほど。
理解できましたね。 ありがとうー ChatGPT.

言葉レベルで理解しておくだけでは、もの足りないので、サンプルを作って動かしてみたいと思いました。

## 簡単なサンプルを作って、もっと深めたいですね。

### 実現したいサンプル
gRPCを使用して簡単なサンプルコードを作成するためには、まずプロトコルバッファ（protobuf）ファイルを定義する必要があります。ここでは、簡単な「挨拶」サービスを作成します。このサービスでは、クライアントがサーバーに名前を送信し、サーバーが「Hello, [名前]!」と応答するというものです。

### 流れ
- Protobufファイルの定義
- サーバー側のコードの作成
- クライアント側のコードの作成

### Step 1: Protobufファイルの定義

greeting.protoという名前のファイルを作成し、以下の内容を記入します。

```
syntax = "proto3";

package greeting;

// サービスの定義
service Greeter {
  // SayHelloは一つの挨拶を返します。
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// HelloRequestはクライアントからのリクエストを定義します。
message HelloRequest {
  string name = 1;
}

// HelloReplyはサーバからのレスポンスを定義します。
message HelloReply {
  string message = 1;
}
```

### Step 2: サーバー側のコード
次に、greeting_server.pyというPythonファイルを作成し、以下のコードを記入します。このコードは、上で定義したプロトコルに従って、クライアントからの挨拶リクエストに応答します。

```python
from concurrent import futures
import grpc
import greeting_pb2
import greeting_pb2_grpc

class GreeterServicer(greeting_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return greeting_pb2.HelloReply(message='Hello, %s!' % request.name)

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    greeting_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()
```

### Step 3: クライアント側のコード
最後に、greeting_client.pyというPythonファイルを作成し、以下のコードを記入します。このコードは、指定された名前を使ってサーバーに挨拶をリクエストし、サーバーからの応答を表示します。

```python
import grpc
import greeting_pb2
import greeting_pb2_grpc

def run():
    channel = grpc.insecure_channel('localhost:50051')
    stub = greeting_pb2_grpc.GreeterStub(channel)
    response = stub.SayHello(greeting_pb2.HelloRequest(name='world'))
    print("Greeter client received: " + response.message)

if __name__ == '__main__':
    run()
```
これでサンプルコードは以上になります。

## 実行してみましょう。

### 事前準備
1.関連パッケージのインストール

```bash
# pipenvを使った場合
pipenv install grpcio grpcio-tools
```
- grpcioは、gRPCのPython実装で、クライアントとサーバーの実行に必要です。
- grpcio-toolsには、.protoファイルからPythonのgRPCコードを生成するために必要なプロトコルバッファコンパイラ（protoc）とPythonのプラグインが含まれています。

2.greeting.protoファイルから必要なPythonコードを生成しておく

```bash
pipenv run python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. greeting.proto
```
このコマンドは、greeting.protoファイルを使って、greeting_pb2.pyとgreeting_pb2_grpc.pyの2つのPythonファイルを生成します。これらは、定義したプロトコルに基づくサーバーとクライアントのコードに必要です。
- -I.オプションは、.protoファイルが存在するディレクトリを指定します（この場合、カレントディレクトリ）。
- --python_out=.と--grpc_python_out=.オプションは、生成されたPythonファイルを出力するディレクトリを指定します（これもカレントディレクトリ）。

## 実行する

### Step 1: サーバーを起動
```bash
pipenv run python greeting_server.py
```
### Step 2: クライアントを実行

```bash
pipenv run python greeting_client.py
```

### 検証

```yaml
Greeter client received: Hello, world!
```

これにより、gRPCを使用してサーバーとクライアント間で通信が正常に行われたことを確認できます。

### 注意点
- サーバーとクライアントが異なるマシン上で実行される場合は、クライアントのコード内のサーバーのアドレスを適宜変更する必要があります。
- 実際のアプリケーションでは、セキュリティを考慮してTLS/SSLを使用した通信を構成することが推奨されます。

### 感想
- 非公開の役割の違う複数台のマシンの間同士の通信は、これを使えば便利だな〜と思いました。
- AI時代だからこそ、新しいスキルの勉強がすごく楽になりました。

### その他
参考資料：　ChatGPT
自分のGithubへアップしておきました。興味があれば、参考にしてください。[こちらへ](https://github.com/cuichangquan/grpc_example)