dubbo-go icon indicating copy to clipboard operation
dubbo-go copied to clipboard

grpc Context failed to transfer attachment data

Open lethexixin opened this issue 4 years ago • 3 comments

What happened: 当使用grpc的Context时, 无法将值从客户端传递到服务端

What you expected to happen:

How to reproduce it (as minimally and precisely as possible): [email protected]

syntax = "proto3";

option java_multiple_files = true;
option java_package = "demo.micro.server.proto";
option java_outer_classname = "sc";
option objc_class_prefix = "demo";

package proto;
option go_package = ".;demo";

// 编译命令 protoc -I ./ demo.proto  --dubbo_out=plugins=grpc+dubbo:.
service SContext {
  rpc FContext(Req) returns (Res){}
}

message Req{
  string data = 1;
}

message Res{
  string data = 1;
}
//客户端:   
req := &demo.Req{}
	res := &demo.Res{}
	err := consumer.GetContextImpl().FContext(context.WithValue(context.Background(), constant.AttachmentKey, map[string]interface{}{
		"socket.addr": "127.0.0.1:12788",
	}), req, res)


//服务端:
func (g *Provider) FContext(ctx context.Context, req *demo.Req) (res *demo.Res, err error) {
	addr := ""
	attachment := ctx.Value(constant.AttachmentKey).(map[string]interface{})
	if v, ok := attachment["socket.addr"]; ok {
		addr = v.(string)
	}
	fmt.Println("test context, addr:", addr)
	return
}

**发现这个attachment是nil ,如下图 **

image

Anything else we need to know?: 完整示例请参考: https://gitee.com/lethexixin/grpc-context-error.git

lethexixin avatar Aug 23 '21 09:08 lethexixin

Unfortunately, attachment feature is exclusive for dubbo protocol, that is, gRPC not supports attachment. So, please consider using other way to pass your own data. BTW, please leave a comment on #2, thanks for your cooperation.

justxuewei avatar Aug 24 '21 13:08 justxuewei

@xavier-niu 谢谢,查资料才发现在 grpc 中,client 与 server 之间通过 context 传递上下文数据的时候,不能使用 context.WithValue,因为 server 端无法获取到 client 自定义的 key, 不过我们可以使用 grpc 提供的 medadata 接口:

//客户端:   
func main() {
        req := &demo.Req{}
	res := &demo.Res{}
	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("socket.addr", "127.0.0.1:12788"))
	err := consumer.GetContextImpl().FContext(ctx, req, res)
}

//服务端:
func (g *Provider) FContext(ctx context.Context, req *demo.Req) (res *demo.Res, err error) {
	if md, ok := metadata.FromIncomingContext(ctx); ok {
		xIds := md.Get("socket.addr")
		fmt.Println("xIds:",xIds)
	}
	return
}

如此,服务端就可以拿到context的值了,不过这个metadata方式只能传string类型

参考:https://mp.weixin.qq.com/s/cwkfYA2rgNIbHom5Yoeizg image

最后:或许可以在 dubbo-go-samples/context 模块的readme.md 文件中描述一下grpc中关于context的问题及解决方案,避免别的小伙伴入坑😳

lethexixin avatar Aug 24 '21 14:08 lethexixin

Thank you for the valuable information. cc @LaurenceLiZhixin

justxuewei avatar Aug 24 '21 14:08 justxuewei