search
LoginSignup
23
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

gRPCクライアントのいろいろ

はじめに

「gRPCサーバーを建てたけど、クライアントからどうやってリクエストするのがいいの?」

という人向けに、gRPCクライアントをいろいろ試した結果をまとめた。

TL;DR

gRPCクライアントはいろいろあるので、以下のように用途に合わせて使う。

前提

  • gRPCサーバーはlocalhostの6565ポートでアクセス可能とする
  • 以下のようなprotoファイルで定義されたサーバーにアクセスする
person.proto

syntax = "proto3";

service Person {
    rpc GetPersons ( Empty ) returns ( PersonsModel ) {}
}

message Empty {}

message PersonModel {
    string name = 1;
    int32 id = 2;
}

message PersonsModel {
    repeated PersonModel person = 1;
}

とにかく一番簡単な方法でリクエストする

grpccを使う。

似たようなツールにgRPC command line toolというのもあるが、ドキュメントを見た感じだとgrpccのほうが洗練されてそう。(gRPC command line toolも試したら追記する。)

特徴

  • コード不要。インストールするだけですぐ使える。
  • 開発時のテストとして使ったりするのに良い。
  • 対話モードでは補完が効くのも素晴らしい。

使い方

対話モードで呼び出す

# protoファイルと接続先gRPCサーバーを指定し、対話モードで起動
$ grpcc --proto ./person.proto --address 127.0.0.1:6565 -i

# getPersonsを呼び出し
$ Person@127.0.0.1:6565> client.getPersons({}, printReply)

対話モードではなく直接呼び出す場合

# --evalオプションで実行するコマンドを指定
$ grpcc --proto ./person.proto --address 127.0.0.1:6565 -i --eval 'client.getPersons({}, printReply)'
出力
{
  "person": [
    {
      "name": "Ranga",
      "id": 10001
    },
    {
      "name": "Ravi",
      "id": 10002
    }
  ]
}

参考

ブラウザからgRPCライクにリクエストする

gRPC Webを使う。

特徴

  • 生成したTypeScriptのコードを使えばクライアント側にも型を強制できる。
  • 実際にはhttp/1.1でアクセス。
  • クライアントとサーバー間に別途grpcwebまたはgRPC WebProxyが必要。
    • サーバーがgoの場合はgrpcwebを使う
    • それ以外の場合はgRPC WebProxyを使う

使い方

protoファイルからコード生成

$ PROTOC_GEN_TS_PATH="./node_modules/.bin/protoc-gen-ts"

$ OUT_DIR="./src/generated"

$ protoc \
    --plugin="protoc-gen-ts=${PROTOC_GEN_TS_PATH}" \
    --js_out="import_style=commonjs,binary:${OUT_DIR}" \
    --ts_out="service=true:${OUT_DIR}" \
    --proto_path="../protofiles" \
    person.proto

生成したコードを使ってTypeScriptで処理を書く

import {grpc} from "grpc-web-client";
import {Empty} from "../../generated/person_pb";
import {Person} from "../../generated/person_pb_service";

getPersons() {
    const empty = new Empty()
    grpc.unary(Person.GetPersons, {
        request: empty,
        host: "http://localhost:8080",//gRPC WebProxyを使う場合は、gRPC WebProxyのURLを指定する
        onEnd: res => {
            const {status, statusMessage, headers, message, trailers} = res
            if (status === grpc.Code.OK && message) {
                console.log(message.toObject())
            }
        }
    })
}

gRPCサーバーがgoの場合は、grpcwebでラップする。

それ以外の場合は、以下のようにgRPC WebProxyを起動する。 (今回はDockerで起動)

$ docker run -p 8080:8080 --rm -it jfyne/docker-grpcwebproxy /grpcwebproxy --backend_addr=host.docker.internal:6565 --run_tls_server=false

参考

https://github.com/improbable-eng/grpc-web/tree/master/ts
https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy

RestAPIライクにリクエストする

Google Cloud Endpoints または gRPC Gatewayを使う。

特徴

  • エンドポイントに対応するURLを設定することでRestAPIライクにリクエストできる。
  • gRPC Web が使えない事情がある場合、ブラウザからリクエストするにはこちらを使う。

使い方

今回検証した Google Cloud Endppoints と Google Kubernetes Engine を連携させるパターンのみ記載する。

Endpoints設定ファイルを作成。ここでエンドポイントのURLを設定する

api_config.yaml
type: google.api.Service
config_version: 3

name: person.endpoints.[GOOGLE_PROJECT_ID].cloud.goog

title: person gRPC API
apis:
- name: Person

http:
  rules:
  - selector: Person.GetPersons
    get: /v1/persons

usage:
  rules:
  - selector: "*"
    allow_unregistered_calls: true

Endpoints設定をデプロイする。

$ protoc --include_imports --include_source_info person.proto --descriptor_set_out out.pb
$ gcloud endpoints services deploy out.pb api_config.yaml

あとはチュートリアルの通り進める。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
23
Help us understand the problem. What are the problem?