Open8
gRPCを試してみる
前提条件
- 端末: Apple Mac mini
- チップ : Apple M2 Pro
- OS : macOS Ventura 13.2.1
- インストーラー : Homebrew
- インストール済コマンド : tree
- プログラミング言語 : Go言語
参考資料
インストール
-
protoc
コマンドを使うためにprotobuf
のインストール- sharl@macMini ~ %
brew install protobuf
実行結果
==> Fetching dependencies for protobuf: abseil
==> Fetching abseil
==> Downloading https://ghcr.io/v2/homebrew/core/abseil/manifests/20230125.3-1
######################################################################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/abseil/blobs/sha256:c789ff211d0d81fba211ffa4abc0a0e5ce430698ae0e590057cbeeb73d
######################################################################################################################## 100.0%
==> Fetching protobuf
==> Downloading https://ghcr.io/v2/homebrew/core/protobuf/manifests/23.4
######################################################################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/protobuf/blobs/sha256:eb86d06abace7c985b21ccac17ea418131e17689c9fdeddbcaa998d7
######################################################################################################################## 100.0%
==> Installing dependencies for protobuf: abseil
==> Installing protobuf dependency: abseil
==> Pouring abseil--20230125.3.arm64_ventura.bottle.1.tar.gz
🍺 /opt/homebrew/Cellar/abseil/20230125.3: 723 files, 10.6MB
==> Installing protobuf
==> Pouring protobuf--23.4.arm64_ventura.bottle.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
/opt/homebrew/share/emacs/site-lisp/protobuf
==> Summary
🍺 /opt/homebrew/Cellar/protobuf/23.4: 389 files, 12.2MB
==> Running `brew cleanup protobuf`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Caveats
==> protobuf
Emacs Lisp files have been installed to:
/opt/homebrew/share/emacs/site-lisp/protobuf
- sharl@macMini ~ %
protoc --version
実行結果
```bash
libprotoc 23.4
- sharl@macMini ~ %
mkdir -p ./dev/grpc/test ; cd ./dev/grpc/test
- sharl@macMini test %
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
実行結果
go: downloading google.golang.org/protobuf v1.31.0
go: downloading google.golang.org/grpc v1.57.0
go: downloading google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
go: downloading google.golang.org/protobuf v1.28.1
- sharl@macMini test %
export PATH="$PATH:$(go env GOPATH)/bin"
- sharl@macMini ~ %
protoc-gen-go --version ; protoc-gen-go-grpc --version
実行結果
protoc-gen-go v1.31.0
protoc-gen-go-grpc 1.3.0
サンプルコードのインストール
- sharl@macMini test %
git clone -b v1.57.0 --depth 1 https://github.com/grpc/grpc-go
実行結果
Cloning into 'grpc-go'...
remote: Enumerating objects: 1349, done.
remote: Counting objects: 100% (1349/1349), done.
remote: Compressing objects: 100% (1144/1144), done.
remote: Total 1349 (delta 212), reused 543 (delta 68), pack-reused 0
Receiving objects: 100% (1349/1349), 2.14 MiB | 11.10 MiB/s, done.
Resolving deltas: 100% (212/212), done.
Note: switching to '87bf02ad24f6cc071d2553eb5d62332194bba1fe'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
- sharl@macMini test %
cd grpc-go/examples/helloworld ; tree
実行結果
sharl@macMini helloworld % tree
.
├── README.md
├── greeter_client
│ └── main.go
├── greeter_server
│ └── main.go
└── helloworld
├── helloworld.pb.go
├── helloworld.proto
└── helloworld_grpc.pb.go
4 directories, 6 files
サンプルコード
greeter_server/main.go
// Package main implements a server for Greeter service.
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
var (
port = flag.Int("port", 50051, "The server port")
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
greeter_client/main.go
// Package main implements a server for Greeter service.
// Package main implements a client for Greeter service.
package main
import (
"context"
"flag"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
defaultName = "world"
)
var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
name = flag.String("name", defaultName, "Name to greet")
)
func main() {
flag.Parse()
// Set up a connection to the server.
conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
サンプルコードの実行
- 別ターミナル起動
- sharl@macMini ~ %
cd ./dev/grpc/test/grpc-go/examples/helloworld ; go run greeter_server/main.go
実行結果
go: downloading google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19
go: downloading google.golang.org/protobuf v1.30.0
go: downloading golang.org/x/net v0.9.0
go: downloading github.com/golang/protobuf v1.5.3
go: downloading google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54
go: downloading golang.org/x/text v0.9.0
2023/08/20 17:24:32 server listening at [::]:50051
- 別ターミナル起動
- sharl@macMini ~ %
cd ./dev/grpc/test/grpc-go/examples/helloworld ; go run greeter_client/main.go
実行結果
2023/08/20 17:29:05 Greeting: Hello world
gRPCサービスのアップデート
Protocol buffersのアップデート
- アップデート前
helloworld/helloworld.proto
syntax = "proto3";
option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (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;
}
- アップデート後
-
Greeter
サービスにSayHelloAgain()
メソッドを追加
-
helloworld/helloworld.proto
........
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
........
gRPCコードの再生成
- sharl@macMini ~ %
cd dev/grpc/test/grpc-go/examples/helloworld
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto
-
helloworld.pb.go
とhelloworld_grpc.pb.go
が更新されていることを確認- sharl@macMini helloworld %
ls -l helloworld
実行結果
total 48
-rw-r--r-- 1 sharl staff 8757 8 20 22:40 helloworld.pb.go
-rw-r--r-- 1 sharl staff 1257 8 20 17:55 helloworld.proto
-rw-r--r-- 1 sharl staff 5730 8 20 22:40 helloworld_grpc.pb.go
サーバーの更新
- greeter_server/main.goに
SayHelloAgain
関数の追加
greeter_server/main.go
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
クライアントの更新
- greeter_client/main.goの
main
関数にSayHelloAgain
関数の呼び出しを追加
greeter_server/main.go
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
サービスの実行
- 別ターミナルでサーバーを実行
- sharl@macMini helloworld %
cd ./helloworld ; go run greeter_server/main.go
実行結果
stat greeter_server/main.go: no such file or directory
sharl@macMini helloworld % pwd
/Users/sharl/dev/grpc/test/grpc-go/examples/helloworld/helloworld
sharl@macMini helloworld % cd ..
sharl@macMini helloworld % pwd
/Users/sharl/dev/grpc/test/grpc-go/examples/helloworld
sharl@macMini helloworld % cd /Users/sharl/dev/grpc/test/grpc-go/examples/helloworld ; go run greeter_server/main.go
2023/08/20 23:20:56 server listening at [::]:50051
- 別ターミナルでクライアントを実行
- sharl@macMini helloworld %
cd /Users/sharl/dev/grpc/test/grpc-go/examples/helloworld ; go run greeter_client/main.go --name=高橋
実行結果
2023/08/20 23:24:49 Greeting: Hello 高橋
2023/08/20 23:24:49 Greeting: Hello again 高橋
- sharl@macMini grpc %
go mod init addressbook
実行結果
go: creating new go.mod: module addressbook
go: to add module requirements and sums:
go mod tidy