11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rust と Cloud Run でサーバレスな (Unary) gRPCサーバを構築する方法

Last updated at Posted at 2020-03-09

概要

ストリーミング対応版の記事を公開しました。最新情報はそちらをご覧ください。
https://qiita.com/K-Kachi/items/8aa6c81990b7e8c6a628

Cloud Run とはグーグルが提供する サーバレスコンピューティングサービス の1つで、ステートレスなコンテナを実行可能なサービスである。
ウェブリクエストに応答する任意のコンテナを実行可能なため自由度が高い。

最近(といっても数か月前だが)、新機能としてUnary gRPC プロトコル(非ストリーミングの gRPC)のサポートが発表された
そこで、Go言語でのチュートリアルを参考にしつつ、試しにRustでgRPCサーバを構築してみた。

RustでgRPC

tonic はgRPCサーバ・クライアントをRustで実装したライブラリである。
このライブラリのリポジトリにあるExamplesをもとに Cloud Run で実行可能なgRPCサーバを構築する。

まずはソースコードをとってくる。

git clone https://github.com/hyperium/tonic.git
cp -r tonic/examples tonic-examples
cd tonic-examples

続いてCargo.tomlをいじる。

Cargo.toml
106c106
< tonic = { path = "../tonic", features = ["tls", "data-prost"] }
---
> tonic = { version = "0.1", features = ["tls", "tls-roots"] }
131c131
< tonic-build = { path = "../tonic-build", features = ["prost"] }
---
> tonic-build = "0.1"

Cloud Run では https での呼び出しが必須のためtls関連が必要になってくる。

tonicが外部クレートとして利用されることによる変更も適宜行う。

sed -i 's/::prost//g' build.rs 

この段階でサンプルコードが動作することを確かめておく。

cargo run --bin helloworld-server
# 別のターミナルで実行
cargo run --bin helloworld-client

Cloud Run で呼び出すための変更

IPアドレスとポート番号を変更する。
ポート番号は環境変数から与える。

src/helloworld/server.rs
30c30,31
<     let addr = "[::1]:50051".parse().unwrap();
---
>     let port = std::env::var("PORT").unwrap_or("8080".into());
>     let addr = format!("0.0.0.0:{}", port).parse().unwrap();

Dockerfileも用意する。証明書関連のパッケージもインストールしていることに注意。
テストが目的なのでコンパイルの最適化を行っていないが、本番環境で利用する場合は--releaseフラグを付けるのを忘れずに。その際、バイナリの出力される場所が./target/debugではなく./target/releaseになることに注意。

FROM rust:1.41.0 as build-env
WORKDIR /app
ADD . .
RUN rustup update && rustup component add rustfmt && cargo build --bin helloworld-server

FROM debian:stretch-slim
WORKDIR /app
RUN apt-get update && apt-get install -y libgcc1 libgomp1 libstdc++6 ca-certificates &&  update-ca-certificates && rm -rf /var/lib/apt/lists/*

COPY --from=build-env /app/target/debug/helloworld-server /app
ENTRYPOINT ["./helloworld-server"]

ビルド

Dockerfileはローカルでビルドしてもよいが、Cloud Buildを使ったほうが個人的には早くて便利。
.gcloudignoreでバイナリフォルダを除いておく。

.gcloudignore
target/
gcloud builds submit --machine-type=n1-highcpu-32 --tag gcr.io/$PROJECT_ID/helloworld-grpc-rust

デプロイ

gcloudコマンドが使用できることを前提とする。
まずリージョンを設定しておく。以下のコマンドでは東京リージョンを選択している。

gcloud config set run/region asia-northeast1

コンテナイメージを指定してデプロイ。

 gcloud run deploy helloworld-grpc-rust --image  gcr.io/$PROJECT_ID/helloworld-grpc-rust

途中で質問されるので Cloud Run (fully managed) と Allow unauthenticated invocations [Yes] と答える。

無事デプロイされるとデプロイ先のURLが出力されるはずである。

gRPC クライアント

出力されたURLをクライアントのコードに貼り付ける。そのままではHTTPSに対応していないので修正する。

src/helloworld/client.rs
0a1,2
> use tonic::transport::{Channel, ClientTlsConfig};
>
10c12,19
<     let mut client = GreeterClient::connect("http://[::1]:50051").await?;
---
>
>     let tls = ClientTlsConfig::new()
>         .domain_name("デプロイ先");
>
>     let channel = Channel::from_static("https://デプロイ先")
>         .tls_config(tls)
>         .connect()
>         .await?;
15a25
>     let mut client = GreeterClient::new(channel);

まとめ

Rustは神。Cloud Run は最強。

11
9
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
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?