在gRPC中,单向流的接收者可以取消流并向发送者发送错误吗?

问题描述 投票:0回答:1

在 gRPC 单向客户端到服务器流中,服务器可以取消流并向客户端返回错误消息吗?

我尝试设置预告片并使用

.SendAndClose()
返回状态消息,但客户端都无法读取。在客户端,
.Send
按预期返回
EOF
错误,但
.CloseAndRecv()
不返回服务器发送的状态消息,并且
.Trailer()
返回空地图。

// 协议缓冲区:

service Foo {
    rpc Eat (stream Food) returns (Status) {}
}

// 服务器:

var Retval pb.Status
Retval.Status = "something went wrong"

emap := make(map[string]string)
emap["error"] = "something went wrong"
MD := metadata.New(emap)

Stream.SetTrailer(MD)
Stream.SendAndClose(&Retval)

// 客户:

err = Stream.Send(Stuff) // returns EOF
if err != nil {
    Status, err := o.Stream.CloseAndRecv() //returns nil, EOF
    
    MD := o.Stream.Trailer() // returns an empty map.
}

有没有一种方法可以在客户端不使用双向流或单独的 RPC 端点向服务器请求状态消息的情况下实现此目的?

grpc grpc-go
1个回答
0
投票

首先,您不需要在原型文件中定义 Status 对象。例如,您可以返回一个名为 Empty 的众所周知的类型。

要执行此操作,您可以执行以下操作:

import "google/protobuf/empty.proto"

service Foo {
    rpc Eat (stream Food) returns (google.protobuf.Empty);
}

这只是一个建议,因为您不需要提供 Status 对象。 gRPC 已经定义了一个可以在 go 代码中使用的定义。

然后在服务器端,当你想返回错误时,你不需要调用

SendAndClose
,因为你的
Eat
函数将具有以下函数声明:

func (*Server) Eat(stream pb.Foo_EatServer) error

您可以使用类似以下代码的内容来发送指定您有错误的状态。

return nil, status.Errorf(
    codes.Internal, // check suitable code
    "A description for the error",
)

在返回之前,您可以设置一个预告片,该预告片将在客户端触发错误。

在客户端,您需要执行以下操作:

trailer := stream.Trailer()
v, exist := trailer["error"]
if exist { // there is an error
    fmt.Println("Error: ", v)
}

如果您需要更多帮助,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.