Bài viết note trong quá trình bắt đầu với gRPC.
Overview
RPC được viết tắt bởi Remote Produce Call. Cho phép gọi một chương trình có thể gọi một hàm được cung cấp bởi chương trình khác.
gRPC = RPC + Protocol Buffers
.
gRPC hoạt động dưới kiến trúc client-server.
Prerequisites
- Máy đã cài đặt sẵn Go - Một trong 3 phiên bản major mới nhất. Hướng dẫn cài đặt: https://go.dev/doc/install
- Protocol buffer compiler, protoc, version 3. Hướng dẫn cài đặt: https://grpc.io/docs/protoc-installation/. Nên tải file zip về và giải nén ra thay vì cài qua apt. Trên ubuntu 18.04, cài qua apt mặc định chỉ là version 3.0.0 gây lỗi ở phần sau của bài viết này.
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.20.3/protoc-3.20.3-linux-x86_64.zip
unzip protoc-3.20.3-linux-x86_64.zip -d ~/.local
rm -rf protoc-3.20.3-linux-x86_64.zip
- Go plugins for the protocol compiler:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 export PATH="$PATH:$(go env GOPATH)/bin"
Kiểm tra:
go version
protoc --version
protoc-gen-go --version
protoc-gen-go-grpc --version
go version go1.19.4 linux/amd64
libprotoc 3.20.3
protoc-gen-go v1.28.1
protoc-gen-go-grpc 1.2.0
Get example
Các phần example được để chung trong repo grpc-go, clone repo này về để có code mẫu. Để ổn định thì sẽ clone code của bản release mới nhất là v1.52.3.
git clone -b v1.52.3 --depth 1 https://github.com/grpc/grpc-go
cd grpc-go/examples/helloworld
Run the example
- Compile và chạy code server:
go run greeter_server/main.go
- Compile và chạy code client:
go run greeter_client/main.go
Ouput:
2023/02/01 13:24:26 Greeting: Hello world
Đến đây, client output Hello world
như trên tức là mình đã kết nối client + server gRPC thành công.
Sửa gRPC service
gRPC service được định nghĩa bằng file .proto (Protocol Buffers). Mình sẽ cần tìm hiểu sâu hơn về file này sau. Trước mắt, chỉ cần đọc và hiểu đoạn khai báo các method RPC của ví dụ trên:
// 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;
}
Tạm hiểu là:
- Khai báo một service
Greeter
- Service
Greeter
chứa một method RPC có tên làSayHello()
, nhận tham số có kiểu làHelloRequest
và trả về kết quả có kiểu làHelloReply
Generate gRPC code
Nhiệm vụ của chúng ta là thêm một method RPC nữa SayHelloAgain()
, hoạt động tương tự như SayHello()
. Sửa file examples/helloworld/helloworld.proto
:
Sử dụng protoc
để generate code cho Go:
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ helloworld/helloworld.proto
Hai file được generate ra là helloworld.pb.go
và helloworld_grpc.pb.go
. Mình đoán .pb.go
là với subfix pb
viết tắt của Protocol Buffers
Xem qua code được generate:
// The request message containing the user's name.
type HelloRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
} // ...
File này có khá nhiều nội dung khác nhưng trước mắt, cái mình nhận thấy nhất là cái message HelloRequest
đã được generate ra, và cũng có field Name
như kỳ vọng.
Tiếp theo, method SayHelloAgain
cũng đã được generate:
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GreeterClient interface { // Sends a greeting SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) // Sends another greeting SayHelloAgain(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}