Golang处理gRPC请求/响应元数据的示例代码

admin 轻心小站 关注 LV.19 运营
发表于Go语言交流版块 教程

在gRPC中,请求和响应的元数据可以用来传递额外的信息,例如认证令牌、追踪信息等。Go语言的gRPC库提供了API来处理这些元数据。以下是一个简单的示例,展示了如何在Go语言中处理gRPC请求和响应的

在gRPC中,请求和响应的元数据可以用来传递额外的信息,例如认证令牌、追踪信息等。Go语言的gRPC库提供了API来处理这些元数据。

以下是一个简单的示例,展示了如何在Go语言中处理gRPC请求和响应的元数据:

1. 定义服务和消息

首先,你需要定义gRPC服务和消息。在.proto文件中添加服务和消息定义,并包含元数据字段。

syntax = "proto3";

package example;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.golang.org/grpc. UnaryServerInterceptor) = {
      // 指定请求和响应的元数据字段
      request: "metadata-bin"
      response: "metadata-bin"
    };
  }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
  // 定义元数据字段
  bytes metadata_bin = 2;
}

2. 实现服务

在你的gRPC服务实现中,你可以使用grpc.UnaryServerInterceptor来访问和修改请求和响应的元数据。

package main

import (
    "context"
    "fmt"
    "log"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    pb "path/to/your/protobuf/package" // 替换为你的protobuf包路径
)

// 定义请求和响应的元数据键名
const (
    mdKeyName = "x-my-meta-key"
    mdKeyValue = "my-meta-value"
)

// 实现gRPC服务
type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    // 访问请求的元数据
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, fmt.Errorf("failed to retrieve metadata")
    }
    val := md.Get(mdKeyName)
    if len(val) == 0 {
        return nil, fmt.Errorf("metadata key not found")
    }

    // 修改响应的元数据
    mdOut, ok := metadata.FromOutgoingContext(ctx)
    if !ok {
        return nil, fmt.Errorf("failed to retrieve metadata for outgoing context")
    }
    mdOut.Set(mdKeyName, mdKeyValue)

    // 创建响应消息
    reply := &pb.HelloReply{
        Message: "Hello " + in.Name,
        // 设置响应的元数据字段
        MetadataBin: []byte("metadata-bin-value"),
    }

    return reply, nil
}

func main() {
    // 创建gRPC服务器
    grpcServer := grpc.NewServer(
        grpc.UnaryInterceptor(grpc_middleware.WithMetadata(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
            // 在这里可以访问和修改元数据
            md, ok := metadata.FromIncomingContext(ctx)
            if !ok {
                return nil, fmt.Errorf("failed to retrieve metadata")
            }
            val := md.Get(mdKeyName)
            if len(val) > 0 {
                log.Printf("Received metadata key: %s, value: %s", mdKeyName, val)
            }
            return handler(ctx, req)
        })),
    )

    // 注册服务
    pb.RegisterGreeterServer(grpcServer, &server{})

    // 监听并启动服务
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    log.Printf("server listening on %v", lis.Addr())
    if err := grpcServer.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

3. 客户端代码

在客户端,你可以在发起gRPC调用时附加元数据,并在接收响应时读取元数据。

package main

import (
    "context"
    "log"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    pb "path/to/your/protobuf/package" // 替换为你的protobuf包路径
)

func main() {
    // 创建gRPC客户端
    conn, err := grpc.Dial(":50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    // 创建gRPC客户端的元数据
    ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(mdKeyName, mdKeyValue))

    // 发起gRPC调用
    c := pb.NewGreeterClient(conn)
    reply, err := c.SayHello(ctx, &pb.HelloRequest{Name: "World"})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }

    // 读取响应的元数据
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        log.Fatalf("failed to retrieve metadata")
    }
    val := md.Get(mdKeyName)
    if len(val) > 0 {
        log.Printf("Received response metadata key: %s, value: %s", mdKeyName, val)
    }

    log.Printf("Greeting: %s", reply.Message)
}

总结

以上示例展示了如何在Go语言中处理gRPC请求和响应的元数据。通过使用metadata包和gRPC的UnaryServerInterceptor,你可以在服务端和客户端访问和修改元数据。这种机制可以用于多种用途,例如添加认证信息、追踪信息或其他自定义数据。在使用元数据时,请确保遵守gRPC的规范和最佳实践。

文章说明:

本文原创发布于探乎站长论坛,未经许可,禁止转载。

题图来自Unsplash,基于CC0协议

该文观点仅代表作者本人,探乎站长论坛平台仅提供信息存储空间服务。

评论列表 评论
发布评论

评论: Golang处理gRPC请求/响应元数据的示例代码

粉丝

0

关注

0

收藏

0

已有0次打赏