Go言語で書くgRPC テクニック:初級編

2025/02/24に公開

はじめに

gRPCは、高速・軽量なRPCフレームワークで、Go言語との相性が良く、マイクロサービス間の通信や API サーバーの実装に最適です。

対象読者

  • gRPCの基本を理解し、実際に使ってみたい方
  • Go言語を使ったシンプルなgRPCサーバー・クライアントを構築したい方

目次

  1. シンプルなUnary RPCの実装
  2. gRPCの接続管理(コネクションプーリング)
  3. リトライとタイムアウトの設定

1. シンプルなUnary RPCの実装

Unary RPCは、1つのリクエストに対して 1つのレスポンスを返す最もシンプルな通信方式です。

1.1 .proto ファイルの定義
.protoファイルで、リクエストとレスポンスの形式を定義します。

example.proto

syntax = "proto3";
package example;

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {
    string name = 1;
}

message HelloResponse {
    string message = 1;
}
  • syntax = "proto3";:Protocol Buffersのバージョン指定
  • service:gRPCのサービスを定義
  • rpc:gRPCメソッドの定義(リクエスト・レスポンス)
  • message:リクエスト・レスポンスのデータ構造

1.2 gRPC コードの生成
以下のコマンドを実行して、Go用のgRPCコードを生成します。

protoc --go_out=. --go-grpc_out=. example.proto
  • example.pb.go:Protocol Buffersのコード
  • example_grpc.pb.go:gRPCのコード

1.3 Server の実装
example.protoで定義したメソッドを実装します。

server.go

package main

import (
    "context"
    "fmt"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "example"
)

type server struct {
    pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
    message := "Hello, " + req.Name
    return &pb.HelloResponse{Message: message}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    fmt.Println("Server is running on port 50051")
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}
  • SayHello メソッド:リクエストを受け取り、メッセージを返す
  • grpc.NewServer():gRPC サーバーを作成
  • RegisterGreeterServer():生成したコードをサーバーに登録

1.4 Client の実装
SayHelloメソッドを呼び出すクライアントを実装します。

client.go

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "google.golang.org/grpc"
    pb "example"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    c := pb.NewGreeterClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "Gopher"})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    fmt.Println("Greeting: ", r.Message)
}
  • grpc.Dial():サーバーに接続
  • NewGreeterClient():gRPCクライアントを作成
  • SayHello()example.proto で定義したRPCメソッドを呼び出す

まとめ

項目 説明
Unary RPC 1つのリクエストに対して1つのレスポンスを返すシンプルな通信方式
Server 実装 SayHello() メソッドを定義して、リクエストに応答
Client 実装 SayHello() メソッドを呼び出して、レスポンスを受け取る

今回は最もシンプルなUnary RPCを使ったgRPCの基本を解説しました。
次は中級編として、ストリーミング RPCインターセプター の使い方をまとめていこうと思います。

Discussion