如何使用 grpc 状态代码并根据客户端构建响应?

How to use grpc status code and build response accordingly to the client?

我想知道当我们发回给用户时,处理 grpc 状态码和响应的最佳方法是什么?

func (us *customerService) FetchResponse(ctx context.Context, request *custPbV1.CustomerRequest) (*custPbV1.CustomerResponse, error) {
    meta := service.MetadataFromContext(ctx)
    clientId := meta.ClientId
    if clientId <= 0 {
        msg := fmt.Sprintf("could not retrieve client info for clientId:%d", clientId)
        // is this right way to return it?
        return nil, status.Error(codes.NotFound, msg)
    }

    resources := request.GetResources()
    if len(resources) == 0 {
        // is this right way to return it?
        err := status.Error(codes.InvalidArgument, "value cannot be null. (Parameter 'resources')")
        return nil, err
    }

    return us.GenerateCustomerInfo(clientId, resources)
}

我的原型很简单-

service CustomerService {
   rpc FetchResponse(CustomerRequest) returns (CustomerResponse) {};
}

message CustomerRequest {
   string resources = 1;
}

message CustomerResponse {
   string proc = 1;
   string data = 2;
}

GenerateCustomerInfo 方法将 return CustomerResponseerror 两者。但是如果有错误那么它会是什么状态码呢?我试图弄清楚人们在 returning grpc 状态代码和对用户的响应时基本上遵循的标准是什么。 return 状态码是否必须返回给客户端?

在响应对象中也有错误 属性 是个好主意吗?任何演示如何 return grpc 状态和响应返回的最佳实践的示例对我都有用。

这样做完全没问题:

err := status.Error(codes.InvalidArgument, "value cannot be null. (Parameter 'resources')")
return nil, err

这将告诉您的客户端存在错误,客户端可以根据该信息检查状态代码和状态消息,如下所示:

resp, err = server.FetchResponse(context.Background(), req)
s, ok := status.FromError(err)

if ok { // there is an error
   fmt.Printf("Code: %d, Message: %s\n", s.Code(), s.Message())
}

GenerateCustomerInfo method will return CustomerResponse and error both. But if there is a error then what status code it will be?

对于 GenerateCustomerInfo 我们没有太多信息可以重现,但我认为你应该 return 像这样:

return &custPbV1.CustomerResponse{
    Proc: "YOUR_PROC",
    Data: "YOUR_DATA",
}, nil

通过 returning nil 在错误中,您将向客户端显示没有错误,并且在前面的代码中给出的 ok 将为 false。

Is it good idea to have error property in response object as well?

为此,您当然可以添加一个错误 属性,但是有必要这样做吗?你可以已经有一个 StatusCode 和一个 Message。它只会不必要地增加有效负载的大小。

But if GenerateCustomerInfo return any error then what status code should I return back? Do I need to define that too?

考虑到 1GenerateCustomerInfo 的潜在实现,例如:

func GenerateCustomerInfo() (*pb.CustomerResponse, error) {
    // some code
    if err {
        st := status.Error(codes.Internal /*or other*/, "a message")
        return nil, err
    }

    return &pb.CustomerResponse{
        Proc: "",
        Data: "",
    }, nil
}

它基本上 return 是 CustomerResponsenil,这完全是父函数所需要的。