如何在 gRPC 中识别断开连接的客户端?

Gus*_*ājs 6 go grpc grpc-go

我正在使用 gRPC 构建 API,并且在服务器端,我想在客户端断开连接时收到通知,识别它并基于此执行一些任务。

到目前为止,我能够使用grpc.StatsHandlermethod检测客户端断开连接HandleConn。我尝试使用上下文传递值,但无法从服务器端访问它们。

客户端:

conn, err := grpc.DialContext(
    context.WithValue(context.Background(), "user_id", 1234),
    address,
    grpc.WithInsecure(),
)
Run Code Online (Sandbox Code Playgroud)

服务器端:

// Build stats handler
type serverStats struct {}

func (h *serverStats) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
    return ctx
}

func (h *serverStats) HandleRPC(ctx context.Context, s stats.RPCStats) {}

func (h *serverStats) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
    return context.TODO()
}

func (h *serverStats) HandleConn(ctx context.Context, s stats.ConnStats) {
    fmt.Println(ctx.Value("user_id")) // Returns nil, can't access the value

    switch s.(type) {
    case *stats.ConnEnd:
        fmt.Println("client disconnected")
        break
    }
}


// Build server
s := grpc.NewServer(grpc.StatsHandler(&serverStats{}))
Run Code Online (Sandbox Code Playgroud)

我想访问从服务器端客户端传递的值。什么是正确的方法,或者有没有其他方法可以识别已断开连接的客户端?

Vit*_*aev 0

我尝试使用上下文传递值,但无法从服务器端访问它们。

您需要显式地将元数据字段设置为客户端上下文:

ctx := context.Background()
ctx = metadata.AppendToOutgoingContext(ctx, "user_id", "1234")
conn, err := grpc.DialContext(cxt, address)
Run Code Online (Sandbox Code Playgroud)

在服务器端,您可以像这样检索它们:

md, ok := metadata.FromIncomingContext(ctx)
Run Code Online (Sandbox Code Playgroud)

正确的方法是什么,或者有其他方法可以识别已断开连接的客户端吗?

这实际上取决于您的用例。我认为 GRPC Stats API 对于一些简单的任务很有用(例如,计算延迟或聚合网络统计数据),但当某些业务逻辑在客户端离开时应该工作时,它不是很有用。我建议defer直接在 GRPC 处理程序中使用调用。另一种选择是实现自定义 GRPC 拦截器。