传递附加参数

传递附加参数 attachment

理解隐式参数传递的最直接方式 http header,它的工作方式与 http header 完全一致,在 GET 或 POST 请求体之外可以传递任意多个 header 参数。而对于 RPC 调用而言,context就是在方法签名的参数之外提供附加参数传递能力,在实现原理上,对于不同的协议,attachment 的实现方式略有不同:

  • 对于 triple 协议,attachment 会转换为标准的 http header 进行传输。
  • 对于 dubbo 协议,attachment 是编码在协议体的固定位置进行传输,具体请参见 dubbo 协议规范。、

/user-guide/images/context.png

注意

  • 在使用 triple 协议时,由于 http header 的限制,仅支持小写的 ascii 字符
  • path, group, version, dubbo, token, timeout 等一些 key 是保留字段,传递 attachment 时应避免使用,尽量通过业务前缀等确保 key 的唯一性。

1.介绍

本文档演示如何在 Dubbo-go 框架中使用 context 上下文传递和读取附加参数,来实现上下文信息传递,可在此查看 完整示例源码地址

2.使用说明

2.1客户端使用说明

在客户端中,使用下述方式传递字段, 示例中 key 为 constant.AttachmentKey 即 “attachment”:

  1. ctx := context.Background()
  2. ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{
  3. "key1": "user defined value 1",
  4. "key2": "user defined value 2"
  5. })

2.2服务端使用说明

在服务端中,使用下述方式获取字段, value的类型为 map[string]interface{}:

  1. attachments := ctx.Value(constant.AttachmentKey).(map[string]interface{})
  2. logger.Infof("Dubbo attachment key1 = %s", value1.([]string)[0])
  3. logger.Infof("Dubbo attachment key2 = %s", value2.([]string)[0])

3.示例详解

3.1服务端介绍

服务端proto文件

源文件路径:dubbo-go-sample/context/proto/greet.proto

  1. syntax = "proto3";
  2. package greet;
  3. option go_package = "github.com/apache/dubbo-go-samples/context/proto;greet";
  4. message GreetRequest {
  5. string name = 1;
  6. }
  7. message GreetResponse {
  8. string greeting = 1;
  9. }
  10. service GreetService {
  11. rpc Greet(GreetRequest) returns (GreetResponse) {}
  12. }

服务端handler文件

源文件路径:dubbo-go-sample/context/go-server/main.go

  1. package main
  2. import (
  3. "context"
  4. "dubbo.apache.org/dubbo-go/v3/common/constant"
  5. _ "dubbo.apache.org/dubbo-go/v3/imports"
  6. "dubbo.apache.org/dubbo-go/v3/protocol"
  7. "dubbo.apache.org/dubbo-go/v3/server"
  8. greet "github.com/apache/dubbo-go-samples/context/proto"
  9. "github.com/dubbogo/gost/log/logger"
  10. )
  11. type GreetTripleServer struct {
  12. }
  13. func (srv *GreetTripleServer) Greet(ctx context.Context, req *greet.GreetRequest) (*greet.GreetResponse, error) {
  14. attachments := ctx.Value(constant.AttachmentKey).(map[string]interface{})
  15. if value1, ok := attachments["key1"]; ok {
  16. logger.Infof("Dubbo attachment key1 = %s", value1.([]string)[0])
  17. }
  18. if value2, ok := attachments["key2"]; ok {
  19. logger.Infof("Dubbo attachment key2 = %s", value2.([]string)[0])
  20. }
  21. resp := &greet.GreetResponse{Greeting: req.Name}
  22. return resp, nil
  23. }
  24. func main() {
  25. srv, err := server.NewServer(
  26. server.WithServerProtocol(
  27. protocol.WithPort(20000),
  28. protocol.WithTriple(),
  29. ),
  30. )
  31. if err != nil {
  32. panic(err)
  33. }
  34. if err := greet.RegisterGreetServiceHandler(srv, &GreetTripleServer{}); err != nil {
  35. panic(err)
  36. }
  37. if err := srv.Serve(); err != nil {
  38. logger.Error(err)
  39. }
  40. }

3.2客户端介绍

客户端client文件,创建客户端,在context写入变量,发起调用并打印结果

源文件路径:dubbo-go-sample/context/go-client/main.go

  1. package main
  2. import (
  3. "context"
  4. "dubbo.apache.org/dubbo-go/v3/client"
  5. "dubbo.apache.org/dubbo-go/v3/common/constant"
  6. _ "dubbo.apache.org/dubbo-go/v3/imports"
  7. greet "github.com/apache/dubbo-go-samples/context/proto"
  8. "github.com/dubbogo/gost/log/logger"
  9. )
  10. func main() {
  11. cli, err := client.NewClient(
  12. client.WithClientURL("127.0.0.1:20000"),
  13. )
  14. if err != nil {
  15. panic(err)
  16. }
  17. svc, err := greet.NewGreetService(cli)
  18. if err != nil {
  19. panic(err)
  20. }
  21. ctx := context.Background()
  22. ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{
  23. "key1": "user defined value 1",
  24. "key2": "user defined value 2",
  25. })
  26. resp, err := svc.Greet(ctx, &greet.GreetRequest{Name: "hello world"})
  27. if err != nil {
  28. logger.Error(err)
  29. }
  30. logger.Infof("Greet response: %s", resp.Greeting)
  31. }

3.3 案例效果

先启动服务端,再启动客户端,可以观察到服务端打印了客户端通过context传递的参数值,说明参数被成功传递并获取

  1. 2024-02-26 11:13:14 INFO logger/logging.go:42 Dubbo attachment key1 = [user defined value 1]
  2. 2024-02-26 11:13:14 INFO logger/logging.go:42 Dubbo attachment key2 = [user defined value 2]

最后修改 September 13, 2024: Refactor website structure (#2860) (1a4b998f54b)