我正在嘗試撰寫一個一元攔截器來向傳入請求添加請求 ID:
func RequestIDInterceptor(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (val interface{}, err error) {
newCtx := ctx
newCtx = createAndSetMetadata(newCtx, metadata.FromIncomingContext, metadata.NewIncomingContext)
newCtx = createAndSetMetadata(newCtx, metadata.FromOutgoingContext, metadata.NewOutgoingContext)
md, ok := metadata.FromOutgoingContext(newCtx)
fmt.Printf("After update. Metadata: %v, Found: %t\n", md, ok)
return handler(newCtx, req)
}
func createAndSetMetadata(ctx context.Context, getter func(context.Context) (metadata.MD, bool),
setter func(context.Context, metadata.MD) context.Context) context.Context {
meta, ok := getter(ctx)
fmt.Printf("Found? %t, Metadata: %v\n", ok, meta)
if !ok {
meta = metadata.New(map[string]string{})
ctx = setter(ctx, meta)
}
meta.Set("X-Request-Id", "TEST_REQUEST_ID")
fmt.Printf("Metadata: %v\n", meta)
return ctx
}
當請求不包含元資料 ( RequestIDInterceptor(context.Background(), nil, nil, handler)) 時,此代碼按預期作業,但如果背景關系包含元資料,則不會填充 ID。本質上,輸出如下所示:
WITHOUT METADATA
Found? false, Metadata: map[]
Metadata: map[x-request-id:[TEST_REQUEST_ID]]
Found? false, Metadata: map[]
Metadata: map[x-request-id:[TEST_REQUEST_ID]]
After update. Metadata: map[x-request-id:[TEST_REQUEST_ID]], Found: true
WITH METADATA
Found? true, Metadata: map[]
Metadata: map[x-request-id:[TEST_REQUEST_ID]]
Found? true, Metadata: map[]
Metadata: map[x-request-id:[TEST_REQUEST_ID]]
After update. Metadata: map[], Found: true
據我了解,這可能發生的原因是metadata.MD通過值而不是通過參考傳遞,因此在createAndSetMetadata回傳時會丟棄更新。如何修復此代碼?
uj5u.com熱心網友回復:
問題是它有效地回傳了在背景關系metadata.FromOutgoingContext中找到的深層副本。metadata.MD您可以檢查來源,它仍然是真實的google.golang.org/[email protected]。
因此,像使用地圖一樣直接寫入它(副本)不會影響MD存盤在背景關系中的內容。
您必須再次呼叫 setter 來傳播新值:
func createAndSetMetadata(/* args */) context.Context {
// ...
return setter(ctx, meta)
}
uj5u.com熱心網友回復:
要為傳入的請求添加請求 ID,一種選擇是您可以通過
攔截器中的context.WithValue將其添加到背景關系中,并通過 grpc 方法中的 key 通過context.Value(key)
示例代碼
func RequestIDInterceptor(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (val interface{}, err error) {
newCtx = context.WithValue(ctx, "X-Request-Id", "TEST_REQUEST_ID")
return handler(newCtx, req)
}
另一種選擇是您可以嘗試通過以下方式將元資料設定回背景關系grpc.SendHeader
示例代碼
func RequestIDInterceptor(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (val interface{}, err error) {
meta, ok := metadata.FromIncomingContext(ctx)
meta.Set("X-Request-Id", "TEST_REQUEST_ID")
grpc.SendHeader(ctx, meta)
return handler(ctx, req)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/518669.html
標籤:去grpc-go
