# gRPC 簡介
gRPC 是由 Google 開發的高性能 RPC 框架,基於 HTTP/2 協議,專為微服務設計。它支持多種編程語言,使用 Protocol Buffers 進行強類型接口定義,並提供雙向流通信。這使得 gRPC 成為跨語言、高效通信的理想選擇,特別適合現代化微服務架構。
# 1. 安裝
首先,我們需要安裝 Go 和 gRPC 的相關工具。
# 安裝 Go
從 Go 官方網站下載並安裝 Go。
# 安裝 gRPC 相關工具
在 Windows 平台上,請按照以下步驟進行安裝:
安裝 protoc 編譯器
從 Protocol Buffers Releases 下載適用於 Windows 的
protoc
編譯器。下載最新版本的壓縮包並解壓縮,然後將bin
目錄添加到系統的PATH
環境變數中。安裝 Go 插件
打開命令提示符或 PowerShell,運行以下命令來安裝
protoc-gen-go
和protoc-gen-go-grpc
插件:go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
設置 Go 二進制目錄到 PATH
確保你的
GOPATH
目錄的bin
子目錄已添加到系統的PATH
環境變數中。可以通過以下命令來確認:set PATH=%PATH%;%GOPATH%\\bin
# 2. 編寫 proto
檔
創建一個 .proto
文件來定義 gRPC 服務和消息:
// example.proto | |
syntax = "proto3"; | |
package example; | |
service ExampleService { | |
rpc GetExample (ExampleRequest) returns (ExampleResponse); | |
} | |
message ExampleRequest { | |
int32 id = 1; | |
} | |
message ExampleResponse { | |
string message = 1; | |
} |
# 3. 使用 protoc
編譯 proto
檔
運行以下命令以生成 Go 代碼:
protoc --go_out=. --go-grpc_out=. example.proto |
這將生成兩個文件:
example.pb.go
: 包含消息的 Go 定義example_grpc.pb.go
: 包含 gRPC 服務的 Go 定義
# 4. 實作 Service
編寫 gRPC 服務的實現:
// server.go | |
package main | |
import ( | |
"context" | |
"log" | |
"net" | |
"google.golang.org/grpc" | |
pb "path/to/your/protos" | |
"google.golang.org/grpc/reflection" | |
) | |
type server struct { | |
pb.UnimplementedExampleServiceServer | |
} | |
func (s *server) GetExample(ctx context.Context, in *pb.ExampleRequest) (*pb.ExampleResponse, error) { | |
return &pb.ExampleResponse{Message: "Hello, World!"}, nil | |
} | |
func main() { | |
lis, err := net.Listen("tcp", ":50051") | |
if err != nil { | |
log.Fatalf("failed to listen: %v", err) | |
} | |
s := grpc.NewServer() | |
pb.RegisterExampleServiceServer(s, &server{}) | |
// Register reflection service on gRPC server. | |
reflection.Register(s) | |
log.Printf("server listening at %v", lis.Addr()) | |
if err := s.Serve(lis); err != nil { | |
log.Fatalf("failed to serve: %v", err) | |
} | |
} |
# 5. 執行
啟動服務器:
go run server.go |
# 6. 配置重試策略
使用 gRPC 的 ServiceConfig
配置來設置重試策略。我們可以在創建客戶端連接時傳遞 ServiceConfig
來指定每個方法的重試行為。以下是示例代碼:
package main | |
import ( | |
"context" | |
"log" | |
"time" | |
"google.golang.org/grpc" | |
pb "path/to/your/protos" | |
) | |
func main() { | |
serviceConfig := `{ | |
"methodConfig": [{ | |
"name": [{"service": "example.ExampleService"}], | |
"retryPolicy": { | |
"maxAttempts": 4, | |
"initialBackoff": "0.1s", | |
"maxBackoff": "1s", | |
"backoffMultiplier": 1.6, | |
"retryableStatusCodes": ["UNAVAILABLE"] | |
} | |
}] | |
}` | |
conn, err := grpc.Dial( | |
"localhost:50051", | |
grpc.WithInsecure(), | |
grpc.WithDefaultServiceConfig(serviceConfig), | |
) | |
if err != nil { | |
log.Fatalf("did not connect: %v", err) | |
} | |
defer conn.Close() | |
client := pb.NewExampleServiceClient(conn) | |
// 發送請求示例 | |
ctx, cancel := context.WithTimeout(context.Background(), time.Second) | |
defer cancel() | |
req := &pb.ExampleRequest{Id: 1} | |
res, err := client.GetExample(ctx, req) | |
if err != nil { | |
log.Fatalf("could not get example: %v", err) | |
} | |
log.Printf("Response: %s", res.Message) | |
} |
# 配置說明
- maxAttempts: 重試的最大次數,包含初始請求次數。例如,設置為 4 表示最多嘗試 4 次(1 次初始請求 + 3 次重試)。
- initialBackoff: 初始重試等待時間。
- maxBackoff: 最大重試等待時間。
- backoffMultiplier: 每次重試等待時間的乘數。
- retryableStatusCodes: 可重試的狀態碼列表,這裡配置為
UNAVAILABLE
。
這段代碼配置了一個 gRPC 客戶端,該客戶端將在請求失敗並返回 UNAVAILABLE
狀態碼時最多重試 4 次,每次重試的等待時間按指數增加,初始等待時間為 0.1 秒,最大等待時間為 1 秒。
當然,以下是第七點的詳細說明,包括如何配置 gRPC 客戶端的重連行為:
# 7. gRPC 重連配置
gRPC 客戶端配置可以通過環境變數或通道選項來實現重連行為。以下是一些關鍵的配置選項:
- 重連初始後退時間(initial backoff time):第一次重試前等待的時間。
- 重連最大後退時間(max backoff time):兩次重試之間的最大等待時間。
- 重連後退乘數(backoff multiplier):用於計算每次重試等待時間的倍數。
以下是一個示例,展示了如何在 Go 中設置這些選項來配置 gRPC 客戶端的重連行為:
package main | |
import ( | |
"context" | |
"log" | |
"time" | |
"google.golang.org/grpc" | |
"google.golang.org/grpc/backoff" | |
pb "path/to/your/protos" | |
) | |
func main() { | |
backoffConfig := backoff.Config{ | |
BaseDelay: 1 * time.Second, // 初始後退時間 | |
Multiplier: 1.6, // 後退乘數 | |
Jitter: 0.2, // 隨機抖動 | |
MaxDelay: 10 * time.Second, // 最大後退時間 | |
} | |
conn, err := grpc.Dial( | |
"localhost:50051", | |
grpc.WithInsecure(), | |
grpc.WithBackoffConfig(backoffConfig), | |
) | |
if err != nil { | |
log.Fatalf("did not connect: %v", err) | |
} | |
defer conn.Close() | |
client := pb.NewExampleServiceClient(conn) | |
// 發送請求示例 | |
ctx, cancel := context.WithTimeout(context.Background(), time.Second) | |
defer cancel() | |
req := &pb.ExampleRequest{Id: 1} | |
res, err := client.GetExample(ctx, req) | |
if err != nil { | |
log.Fatalf("could not get example: %v", err) | |
} | |
log.Printf("Response: %s", res.Message) | |
} |
# 配置說明
- BaseDelay: 初始後退時間,這是在第一次重試之前的等待時間。在這個示例中設置為 1 秒。
- Multiplier: 後退乘數,用於計算每次重試的等待時間。在這個示例中設置為 1.6,表示每次重試等待時間是上一次的 1.6 倍。
- Jitter: 隨機抖動,增加一點隨機性以避免重試請求集中在同一時間點。在這個示例中設置為 0.2。
- MaxDelay: 最大後退時間,兩次重試之間的最大等待時間。在這個示例中設置為 10 秒。
這段代碼配置了一個 gRPC 客戶端,它將根據設置的後退策略在連接失敗時進行重連。這些配置可以幫助應對網絡不穩定或服務暫時不可用的情況。