LoginSignup
138
97

More than 5 years have passed since last update.

nginx に実装された gRPC サポートを試してみる

Posted at

Announcing gRPC Support in NGINX ということで、nginx 1.13.9 で gRPC サポートが入り、HTTP と同じように gRPC ストリームを扱えるようになるようです。めでたい!

grpc_pass ディレクティブが新規に実装され、grpc:// と grpcs:// なバックエンドに対してリバースプロキシを行えるようになるようです。これを使って、

  • TLS 終端を nginx にやってもらったり
  • 複数のバックエンドを置いて柔軟にロードバランスしてもらったり
  • 同一のエンドポイントに複数 gRPC service を設定して、nginx にルーティングしてもらったり

などの設定をすることが可能になるようです。

まだ正式にリリースされているわけではないので、今回は HEAD を持ってきて、リリースに載っている例を試してみます。

下準備

今回は適当に EC2 で Ubuntu 16.04 インスタンスを立ち上げました。必要なパッケージをインストールし、https://hg.nginx.org/ から HEAD の tar.gz を持ってきて、ビルドします。

特に configure にオプションを渡さなければ、すべてのファイルが /usr/local/nginx 以下に配置されます。

$ sudo apt install build-essential libssl-dev libpcre3-dev
$ curl -O https://hg.nginx.org/nginx/archive/tip.tar.gz
$ tar xvf tip.tar.gz
$ cd nginx-c2a0a838c40f
$ ./auto/configure --with-http_ssl_module --with-http_v2_module
$ make
$ sudo make install

# nginx を foreground で起動
sudo ./nginx -g 'daemon off;'

また、実験用の gRPC サーバー・クライアントを準備します。今回は grpc/grpc の examples にある、Python 版を使います。いつもの greeter のやつですね。

$ sudo apt install python-pip3
$ sudo pip3 install grpcio-tools
$ git clone https://github.com/grpc/grpc.git

# 試しに動かしてみる
$ cd ~/grpc/examples/python/helloworld
$ python3 greeter_server.py
$ python3 greeter_client.py
2018/03/18 14:46:12 Greeting: Hello world

普通にリバースプロキシ

http {
    server {
        listen 80 http2;  // http2 必須

        location / {
          grpc_pass grpc://localhost:50051;
        }
    }
}

greeter_client.py を書き換えて、 localhost:80 を向くようにし、実行。

$ python3 greeter_client.py
Greeter client received: Hello, you!

$ tail /usr/local/nginx/logs/access.log
127.0.0.1 - - [18/Mar/2018:16:46:09 +0000] "POST /helloworld.Greeter/SayHello HTTP/2.0" 200 18 "-" "grpc-python/1.10.0 grpc-c/6.0.0 (manylinux; chttp2; glamorous)"

あっさりリバースプロキシできましたね。

普通に TLS 終端してもらう

server {
    listen 443 ssl http2;

    ssl_certificate ssl/cert.pem;
    ssl_certificate_key ssl/key.pem;
}

今回は証明書を用意するのが面倒だったので試さなかったが、これだけで普通に grpcs:// を受けられるようになる、とのこと。外部のクライアントとの間は grpcs で通信したいが、内部の Microservice 同士は平文でいい…… といったケースで便利?

複数 gRPC Service へのルーティング + ロードバランス + REST API との共存例

別の Service ("DaininkiService") を提供する gRPC サーバーを立ててみて、ロードバランスさせてみます。

upstream daininki_service_servers {
    # helloworld.Daininki を提供するサーバーたち
    server localhost:50052;
    server localhost:50053;
}

server {
    listen 80 http2;

    location /helloworld.Greeter {
        grpc_pass grpc://localhost:50051;
    }

    location /helloworld.Daininki {
        # HTTP と同じようにロードバランス
        grpc_pass grpc://daininki_service_servers;

        error_page 502 = /error502grpc;
    }

    # バックエンドが unavailable だった場合は gRPC 形式でエラーを返す
    location = /error502grpc {
        internal;
        default_type application/grpc;
        add_header grpc-status 14;
        add_header grpc-message "unavailable";
        return 204;
    }

    location / {
        proxy_pass http://rest_api_server;
    }
}

大人気である DaininkiService は大人気なので、2つのサーバーを構えて nginx にロードバランスしてもらっていることが分かると思います。また、バックエンドのいずれもが応答できなかったときは、nginx 自身に application/grpc 形式の応答を返してもらうことも出来るようです。

アナウンスのページには REST API のような non-gRPC サービスも同じ endpoint に混ぜることができる、と書いてありますが、この例のように location / を記述しても上手く動作しませんでした……。上手く使えた場合、REST API を提供していたアプリケーションを拡張して gRPC も話せるようにするようなケースでは便利ではないでしょうか。

今後

gRPC 関連機能の実装はメーリングリストでのフィードバックを受け、今後の nginx のリリースに含まれるようです。期待ですね!

138
97
0

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
  3. You can use dark theme
What you can do with signing up
138
97