🦀

Rust🦀で簡易gRPCサーバーを作成して、BloomRPCで動作確認してみたの巻

2024/03/18に公開

gRPCについて完全に理解したので、せっかくなのでRustで簡易gRPCサーバーを作成してみたよ!

あと、動作確認にはBloomRPCアプリを使ったから簡単だったよ😊

Rust🦀で簡易gRPCサーバー作成!

完成したリポジトリ:https://github.com/ask-nugey/rust-grpc

いきなりだけど、最終的なディレクリ構成は以下のようになるよ✨↓

rust-grpc/
├── proto/
│   └── greeter.proto
├── src/
│   └── main.rs
├── target/
├── Cargo.lock
├── Cargo.toml
└── build.rs

今回は「名前(文字列)を送ったら挨拶(文字列)を返す」めちゃ簡単なgRPCサーバーを作るよ!
作ったら動作確認もするよ!

実際にプログラミング✨

まずはプロジェクトを作ろー💪

cargo new rust-grpc

protoファイルを作成する!

greeter.protoを作るよ!

rust-grpc/
└── proto/
    └── greeter.proto

greeter.protoファイル↓

syntax = "proto3";

package greeter;

message HelloRequest {
  string name = 1;
}

message GoodbyeRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

message GoodbyeReply {
  string message = 1;
}

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayGoodbye (GoodbyeRequest) returns (GoodbyeReply) {}
}

protoについてはこっち↓を見てね!
https://zenn.dev/articles/8351a9886f64c4/edit

Rustのコードを書くよ!

RustでgRPCサーバーを作るときは、warpとかactic-webじゃなくてtonicを使うみたい!

Cargo.tomlファイル↓

[package]
name = "rust-grpc"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tonic = "0.11.0"
prost = "0.12.3"
tokio = { version = "1.36.0", features = ["full"] }

[build-dependencies]
tonic-build = "0.11.0"

[[bin]]
name = "greeter_server"
path = "src/main.rs"

[build]
# `build.rs`をビルドスクリプトとして指定
script = "build.rs"

これでprotoファイルからコンパイルしたり、gRPC通信が書けるよ!

protoファイルからRustのコードを生成する!

以下のコード↓でgreeter.protoファイルから、Rustの型定義とgRPCサービス(greeter)の実装を含むコードを生成できるよ!

fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::compile_protos("proto/greeter.proto")?;
    Ok(())
}

このコードはcargo buildするときに自動で実行されるんだ〜

サーバーのコードを書く!!

gRPCサーバーの起動とgreeterサービスの実装をmain.rsに書いていくよ!

まずは、protoから型とかをインポートしよー!

use tonic::{transport::Server, Request, Response, Status};

// greeter.protoから自動生成されたRustコードを読み込む
pub mod greeter {
    tonic::include_proto!("greeter"); // package名に対応
}

greeterから型をインポート
use greeter::{
    greeter_server::{Greeter, GreeterServer},
    GoodbyeReply, GoodbyeRequest, HelloReply, HelloRequest,
};

protoから型をインポートしたら、greeterサービスのメソッド(say_helloとsay_goodbye)を実装するよ〜

#[derive(Default)]
pub struct MyGreeter {}

#[tonic::async_trait]
impl Greeter for MyGreeter {
    async fn say_hello(
        &self,
        request: Request<HelloRequest>, // リクエストの型
    ) -> Result<Response<HelloReply>, Status> { // レスポンスとエラーの型
        let reply = greeter::HelloReply {
            message: format!("Hello, {}!", request.into_inner().name),
        };
        Ok(Response::new(reply))
    }

    async fn say_goodbye(
        &self,
        request: Request<GoodbyeRequest>, // リクエストの型
    ) -> Result<Response<GoodbyeReply>, Status> { // レスポンスとエラーの型
        let reply = greeter::GoodbyeReply {
            message: format!("Goodbye, {}!", request.into_inner().name),
        };
        Ok(Response::new(reply))
    }
}

最後にサーバーを実行して、say_helloとsay_goodbyeを組み込む!

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse()?;
    let greeter = MyGreeter::default();

    println!("GreeterServer listening on {}", addr);

    Server::builder()
        .add_service(GreeterServer::new(greeter))
        .serve(addr)
        .await?;

    Ok(())
}

これでgRPCサーバーはできたはず!

起動してみてね↓

cargo run

gRPCを実行して、BloomRPCで確認するぞ!

起動してもちゃんと機能するのか確認したい!

そんなときにBloomRPCアプリで動作確認が秒でできてすごかった

BloomRPCアプリのインストール

brew install --cask bloomrpc

bloomrpcを起動したらprotoファイルを読み込もう!!

「+」ボタン↓を押して、

今回作ったプロジェクトの「greeter.proto」を選んでね↓

そしたら、左のパネルに出てきた「SayHello」か「SayGoodbye」をクリックしてタブを開こ!

「0.0.0.0:3009」って書いてあるところは、今回のプロジェクトに合わせて「localhost:50051」に書き換えてね!

んで、中央の緑の「▶️」ボタンを押すとレスポンスが表示されるはずだよ!

終わりに

なんかうまくいかないとかあったら言ってね!
また、間違いやご不明点があればコメントいただければ幸いです😊

ヌギーのSNS(連絡先など)

Discussion