我想了解 golang、gRPC 和 protobuf 的良好实践。
我正在实现以下 gRPC 服务
service MyService {
rpc dosomethink(model.MyModel) returns (model.Model) {
option (google.api.http) = { post: "/my/path" body: "" };
}
}
我编译了 protobuf。事实上,protobuf 给我们提供了一个从 http 到 grpc 的 httpproxy。
实现该服务的代码:
import "google.golang.org/grpc/status"
func (Abcd) Dosomethink(c context.Context, sessionRequest *model.MyModel) (*model.Model, error) {
return nil, status.New(400,"Default error message for 400")
}
我想要一个 400 http 错误(在 http 代理中),并显示消息“400 的默认错误消息”,该消息有效,但 http 错误始终为 500。
您知道有关此的任何帖子或文档吗?
您需要返回空的
model.Model
对象,以便 protobuf 能够正确序列化消息。
尝试
import "google.golang.org/grpc/status"
func (Abcd) Dosomethink(c context.Context, sessionRequest *model.MyModel) (*model.Model, error) {
return &model.Model{}, status.Error(400,"Default error message for 400")
}
错误处理程序:
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
return data, status.Errorf(
codes.InvalidArgument,
fmt.Sprintf("Your message", req.data),
)
需要有关错误处理的更多信息,请查看下面的链接。
在 gRPC 中,我们永远不应该在成功响应中返回错误。应该就像我们返回 successResponse 或返回 errorResponse。如果我们返回例如 errorResponse 那么 successResponse 将是
nil
。
Golang 有一个名为
status
的包,广泛用于错误处理。它有一个内部函数 Error()
将其转换为返回的 error
对象。
// status.proto
message Status {
// The status code, which should be an enum value of [google.rpc.Code]
int32 code = 1;
// error-message
string message = 2;
// A list of messages that carry the error details.
repeated google.protobuf.Any details = 3;
}
因此,我们应该在
code
字段中发送 grpc 错误代码。我们可以在 message
字段中发送与发生的错误相关的一般消息或错误代码,例如“VALIDATION_ERROR”、“AUTH_ERROR”等。并且,附加信息或堆栈跟踪或开发人员错误消息应在 details
字段中发送。
示例1:
err := status.Errorf(codes.InvalidArgument, "First Name is required")
示例2:
//error.proto
message ErrorDetails {
string code = 1;
string additional_info = 2;
}
err := status.Errorf(codes.InvalidArgument, "First Name is required")
err, _ := err.WithDetails(&ErrorDetails{
Code: "VALIDATION_ERROR",
AdditionalInfo: "Error occured at third-party API"
})
我们还可以创建类似于 Status 的自定义结构,它应该实现 2 个方法 -
Error()
和 GRPCStatus()
,gRPC 将负责其余工作。
注意:以防万一,我们使用 grpc-gateway 并通过代理为 grpc 和 http 服务器提供服务。在该场景中,我们可以使用
WithErrorHandler
创建自定义拦截器,将 status
对象隐藏为对客户端更友好的错误对象。