🧪

Spring gRPC に触れてみた

に公開

はじめに:記事の概要

対象の読者

  • Spring Boot を触ったことがある方
    • Spring Boot に関しては基本的なことについて知っているものとして書いています

この記事で書くこと

  • Spring gRPC の概要
    • 公式の情報を元に概要のまとめ
    • 雰囲気重視
  • Spring gRPC を使った簡単なデモ
    • サンプルコードを使って雰囲気を掴む

この記事で書かないこと

  • gRPC そのものの仕組み
    • それは、ほかの記事とか書籍をあたってほしい
  • Spring Boot に関する話
    • それも、ほかを参照してほしい

ここから本題

Spring gRPC とは

Spring gRPC とは、Spring Boot や Spring Framework をはじめとする Spring エコシステムの 1 つです。
ただし、その中でも、Spring Projects Experimental と呼ばれる実験的なプロジェクトに含まれます。

実験的なプロジェクトなので、大きな変更が生じたり、正式なサポート体制がなかったりするので、実戦投入には不安が残ります。[1]

プロジェクト自体は、2024年9月に公開され、利用可能な最新バージョンは2025年3月に公開されている 0.5.0 です。[2]

また、少し前ですが Spring の公式ブログでこのような記事が公開されました。

This Month in Spring - January 2025 - Tanzu

こちらの記事で、Spring gRPC に関して以下の通り、言及がされています。

Spring gRPC

簡単にまとめると、以下です。

  • Spring Boot で GraalVM 対応の gRPC サービスを簡単に構築可能
    • Spring Initializr で Spring gRPC を選択
    • proto フォルダに定義ファイルを作成・配置
    • ビルドツールでスタブを生成
    • 作成されたスタブを元にサービス実装
  • その他
    • Actuator を用いてメトリクスの取得が可能
    • 将来的には、Spring Security との連携による保護も予定
    • GraalVM のネイティブバイナリにコンパイルが可能
    • 紹介動画も作成中

また、Spring Developer Advocate である Josh Long 氏が運営している A Bootiful Podcast にて、Dave Syer 氏[3] を招いて、今回の Spring gRPC について話されています。

https://spring.io/blog/2025/01/09/a-bootiful-podcast-dr-dave-syer-on-spring-grpc
https://bootifulpodcast.podbean.com/e/dr-dave-syer-on-the-new-and-nifty-spring-grpc-project/

こちらも簡単にまとめると、

  • gRPC に関する一般的な内容
    • gRPC の簡単な概要
    • Spring gRPC 以前の Java での gRPC 実装について
  • Spring gRPC について
    • プロジェクトの立ち上げのきっかけ
    • 提供中の機能
      • Actuator サポート
      • Micrometer によるメトリクス収集のサポート
      • GraalVM ネイティブイメージのサポート
      • インターセプターを利用して、サービス前後に処理を実装可能
    • 提供予定の機能
      • Spring WebFlux での利用
      • Spring Security との統合
  • 今後のマイルストーン
    • 1.0 リリースに向けて開発を進めている

また、この Podcast では、Spring gRPC 以外にも Spring AI MCP や David Syer 氏自身の話も出ていて興味深かったです。

サンプルコードを試してみた

ここからは、Spring gRPC を試してみます。
(以降、Spring gRPC のプロジェクトにあるサンプルコードを元に試しています。)

また、使用しているバージョンは下記の通りです。

  • Spring Boot : 3.4.3[4]
  • Spring gRPC : 0.5.0[5]

Spring Initializr を用いた Spring gRPC の導入

各 IDE でも、本家の Spring Initializr のどちらでも OK です。

I/O のカテゴリ内に Spring gRPC があるので、それを選択します。

Spring InitializrSpring Initializr の画面

IntelliJ IDEA の Spring InitializrIntelliJ IDEA の Spring プロジェクト作成の画面

上記で Spring gRPC を選択して、プロジェクトを作成すると以下のように src/main/proto ディレクトリが作成されます。

proto ディレクトリ空のディレクトリ proto が生成

proto ファイルの作成

上記の proto ディレクトリに下記の hello.proto のような proto ファイルを配置します。[6]

hello.proto
syntax = "proto3";

option java_multiple_files = true;
option java_package = "org.springframework.grpc.sample.proto";
option java_outer_classname = "HelloWorldProto";

// The greeting service definition.
service Simple {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc StreamHello (HelloRequest) returns (stream HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

ベースとなるコードの生成

proto ファイルを配置した後に、Maven や Gradle といったビルドツールでビルドをすると、下記のようなコードが生成されます。

ビルドして生成されたコード群言わずもがなですが、Maven だと target、Gradle だと build に生成

処理の定義

上記で生成されたコードを用いて、処理を実装していきます。[7]

GrpcServerService.java
@Service
public class GrpcServerService extends SimpleGrpc.SimpleImplBase {

  private static Log log = LogFactory.getLog(GrpcServerService.class);

  @Override
  public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    log.info("Hello " + req.getName());
    if (req.getName().startsWith("error")) {
      throw new IllegalArgumentException("Bad name: " + req.getName());
    }
    if (req.getName().startsWith("internal")) {
      throw new RuntimeException();
    }
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello ==> " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }

  @Override
  public void streamHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    log.info("Hello " + req.getName());
    int count = 0;
    while (count < 10) {
      HelloReply reply = HelloReply.newBuilder().setMessage("Hello(" + count + ") ==> " + req.getName()).build();
      responseObserver.onNext(reply);
      count++;
      try {
        Thread.sleep(1000L);
      }
      catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        responseObserver.onError(e);
        return;
      }
    }
    responseObserver.onCompleted();
  }
}

Spring Boot アプリケーションの起動

Spring Boot アプリケーションを起動させます。

上記の画像の通り、gRPC サーバーが立ち上がります。
また、赤線で囲った通り、デフォルトのポートは 9090 になりますので、Spring Boot のデフォルトの 8080 でないことに注意が必要です。

gRPC リクエストの検証

最後に gRPC サーバー(Spring Boot)を立ち上げた状態で、grpcurl でリクエストしてみます。
先に定義した GrpcServerService.java と合わせて見るとわかりやすいと思います。

Unary RPC の場合

grpcurl -d '{"name":"Hi"}' -plaintext localhost:9090 Simple.SayHello

>\u003e に文字化けしていますが。。。

サーバー側ストリーミングRPC の場合

grpcurl -d '{"name":"Hi"}' -plaintext localhost:9090 Simple.StreamHello

こっちも >\u003e に文字化けしていますが。。。

まとめ

今回、Spring gRPC について、簡単に紹介しました。
Spring Boot を使った開発に慣れ親しんでいる方であれば、定義した proto ファイルから生成されたスタブに対して、gRPC サービスを実装することはラクに感じるはずです。

まだ、実験的なプロジェクトなので、プロダクションレディなプロダクトに使うのは心許ないです。早く正式なプロジェクトに格上げされることに期待したいです。

脚注
  1. なので、本記事の内容含めて、用法用量はきちんと判断していただくことをお願いします! ↩︎

  2. Spring の公式リファレンス上は 0.6.0-SNAPSHOT となっています。(記事執筆の2025年3月現在) ↩︎

  3. Spring Boot、Spring Cloud、Spring Batch の Founder。https://github.com/dsyer ↩︎

  4. 執筆時点での最新版です。https://github.com/spring-projects/spring-boot/releases/tag/v3.4.3 ↩︎

  5. 執筆時点での最新版です。https://github.com/spring-projects-experimental/spring-grpc/releases/tag/v0.5.0 ↩︎

  6. コードの元ネタはこちらです。 ↩︎

  7. コードの元ネタはこちらです。 ↩︎

BABY JOB  テックブログ

Discussion