🔖

Go+gRPCの環境を作る(実装中)

2022/04/20に公開

GoでAPIを実装したい

  • Go+gin+Air環境作る
    • Airはフロントエンドの「yarn run watch」のようなHOTリロードができる(いちいちコンパイルするの手間を省ける)
    • https://qiita.com/hiro5963/items/5867e254ff3a19f5850b
      • go.mod:module管理ファイル(依存関係の解消)

gRPC-webのサンプルを動かしてみる

https://github.com/uid4oe/grpc-web-demo

  • 動いた!!

https://github.com/takat0-h0rikosh1/envoy-grpc-proxy

  • goやnodeのローカルへのインストール要
  • envoyの起動確認できた

https://github.com/okmttdhr/grpc-web-react-hooks

ENV PATH=$PATH:$GOPATH/bin
ENV GOPATH=$HOME/go
$ docker-compose logs

proto_1   | + SERVER_OUTPUT_DIR=server/messenger
proto_1   | + CLIENT_OUTPUT_DIR=client/src/messenger
proto_1   | + protoc --version
proto_1   | + protoc --proto_path=proto messenger.proto --go_out=plugins=grpc:server/messenger --js_out=import_style=commonjs:client/src/messenger --grpc-web_out=import_style=typescript,mode=grpcwebtext:client/src/messenger
proto_1   | libprotoc 3.20.0
proto_1   | protoc-gen-go: unable to determine Go import path for "messenger.proto"
proto_1   | 
proto_1   | Please specify either:
proto_1   |     • a "go_package" option in the .proto source file, or
proto_1   |     • a "M" argument on the command line.
proto_1   | 
proto_1   | See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
proto_1   | 
proto_1   | --go_out: protoc-gen-go: Plugin failed with status code 1.
envoy_1   | [2022-04-20 11:21:39.505][8][critical][main] [source/server/server.cc:117] error initializing configuration '/etc/envoy/envoy.yaml': Protobuf message (type envoy.config.bootstrap.v3.Bootstrap reason INVALID_ARGUMENT:(static_resources.clusters[0]) hosts: Cannot find field.) has unknown fields
envoy_1   | [2022-04-20 11:21:39.506][8][info][main] [source/server/server.cc:939] exiting
envoy_1   | Protobuf message (type envoy.config.bootstrap.v3.Bootstrap reason INVALID_ARGUMENT:(static_resources.clusters[0]) hosts: Cannot find field.) has unknown fields

proto

バージョン指定

syntax = "proto3";

他のパッケージからのインポート

import "google/protobuf/empty.proto";

名前の衝突を避ける為にパッケージ名を指定

package messenger;

APIにおけるサービスを定義する。

  • 引数と返り値に「stream」がつくと単方向/双方向ストリーミングRPCを表現する
  • 引数なしを定義するときは、"google/protobuf/empty.proto"をインポートして”google.protobuf.Empty”を引数に指定
service Messenger {
  rpc GetMessages (google.protobuf.Empty) returns (stream MessageResponse) {}
  rpc CreateMessage (MessageRequest) returns (MessageResponse) {}
}

複数のフィールドを持ったメッセージ型(フィールド型とメッセージ型を利用可)

message MessageRequest {
  string message = 1;
}

envoy.yml

  • 使用されるAPI構成を定義
    • static_resources:静的構成API(すべての設定が定義ファイルで事前定義されていることを意味)
  • リスナーの定義
    • listeners:リクエストをリッスンするIPアドレスやポートなど、ネットワークに関する設定
  • リクエストの処理方法を定義:filter_chains
  • clusters

参考

  • 参考
    • gRPC+Go を触ってみたので、ざっくり纏めてみた [ハンズオンつき]:https://qiita.com/mnoji/items/20895275d923f02821fd
    • https://www.amazon.co.jp/dp/B087R87L6Z
      • REST:リソース(オブジェクト)が中心、HTTPメソッドで操作
      • Remote Procedure Call:遠隔手続き呼び出し
        • あるサービスから別のサービスのサブルーチン・クラス・関数等を呼び出す技術
        • 違うアプリケーションのロジックをあたかも自分のアプリケーションの中に実装されているかのように扱うことができる
        • NFS(分散ファイルシステム)の一部で使う為に開発した技術
      • RPC
        • JSON-RPC
        • SOAP
        • Apache Thrift
      • RESTとの違い
        • レスポンスにJSONを使うかといったフォーマットの問題ではない
        • REST:規格が厳格に決められているわけでなく設計原則。原則に沿って自分で仕様を決めて実装する
        • RPC:規格や仕様に沿って実装されたライブラリやフレームワークとして提供、フレームワークを学習するところがまず課題に
      • gRPCのメリット
        • HTTP/2による高速な通信
          • 通信時のデータがテキストでなくバイナリ→小さな容量で転送できネットワーク内のリソースを効率的に使用できる
          • ひとつのコネクションで複数のリクエスト/レスポンスをやり取りできる
          • コネクションが常時貼られっぱなしの状態になる→ヘッダを都度送る必要がないので通信が効率的
          • マイクロサービスの内部APIの通信規格として評価されている
            • マイクロサービスの問題:複数のサービスのやりとりにプライベートなAPIリクエストが増える→応答速度の遅延がサービスのボトルネックに
        • ProtocolBuffers(gRPCの最大のメリット)
          • ProtocolBuffersのフォーマットにシリアライズ(複数の要素を一列に並べる操作や処理のこと)してデータをやりとりする
          • https://qiita.com/allein-s/items/c125af381600c5b7fa28
          • シリアライザ自体はカスタマイズすればJSONなどのレスポンスに変えることもできる
          • .protファイルというインタフェース記述言語
          • .protoファイルを書いてコンパイラを実行すると任意の言語のサーバ・クライアント用コードを生成してくれる
          • 自分でAPIインタフェースを実装したり、シリアライズされたデータのエンコード・デコード処理を書く必要はない
          • gRPCではスキーマが最初に書かれるので.protoファイルでAPIの仕様が分かる(スキーマファーストになる)
          • 静的型付けになる(各言語のコード生成時に適切な型へ変換される)
        • 柔軟なストリーミング形式
          • 1:1のリクエスト/レスポンス以外に単方向/双方向のストリーミングRPCに対応
          • サーバストリーミング
            • 時間のかかる処理に非同期にレスポンスを返す
            • クライアントからのリクエスト後、クライアントは待機状態としサーバの状態変更に応じて情報を随時プッシュ
          • クライアントストリーミング
            • クライアントからリクエストを分割して送信→全てのリクエストを送る前にサーバ側で逐次処理を開始できる
            • サーバ側は全てのリクエストを受け取ってからレスポンスを返す
            • 大きなデータを分割してアップロードしたい場合などに有用
          • 双方向ストリーミング
            • クライアントから初めてのリクエストが送られた後、サーバ・クライアントどちらも任意のタイミングでリクエスト・レスポンスを送れる
            • ユースケースとしてはチャットやゲーム
            • REST APIではストリーミングを行えないのでsocket serverを別途建てる必要がある
            • gRPCの場合単一のサーバで双方向通信が必要なAPIとしても対応可
      • gRPCのデメリット
    • https://qiita.com/hiro_hira/items/a4e06a3e7e8c8dfef4df
    • https://zenn.dev/dictav/articles/grpc-web-app
      • ブラウザはネイティブでgRPCを話すことができない
      • gRPC Web にはgRPC Web Proxyが必要になる
    • https://nekonenene.hatenablog.com/entry/grpc-nginx-proxy
      • nginx + grpc + goの実装
    • https://github.com/gami/grpc_example
      • 実装サンプル
    • https://github.com/HirotoOhria/grpc-demo
      • スターティングgRPCの実装サンプル
    • https://qiita.com/jackchuka/items/2072191efccec8a2d859
      • ローカル環境でgRPCをデバッグする方法
    • https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md
      • ブラウザ上の制限等
  • Docker
    • context is 何?
      • Dockerはコンテキスト(カレントディレクトリ)の外のファイルにはアクセスできない仕様
      • コンテキストをルートディレクトリにすれば共有ディレクトリをカレントディレクトリ(Dockerが入っているディレクトリ)外にしても使える
      • https://qiita.com/sam8helloworld/items/e7fffa9afc82aea68a7a
    • docker rmi:イメージの削除
    • docker buildx:Docker ビルドと同様のユーザー操作を提供し、さらにスコープ化されたビルダーインスタンス、複数ノードへの同時ビルドなど、数多くの新機能を提供
    • docker push:リポジトリまたはレジストリに対してイメージをプッシュ

Discussion