这是我参与「第五届青训营」伴学笔记创作活动的第 4 天
目前应该很少有企业选择服务单机运行了,几乎都选择了容器化部署,模块拆分,来防止各个模块之间造成的影响。同时也有利于扩容。
基本架构
在开发过程中,我选择直接使用 go-zero 提供的 Api 作为服务网关,与其他服务之间采用 Rpc 进行通信。
比如我选择将用户验证identity作为一个单独的服务,只负责处理用户登录,用户注册,身份验证。
Api 类似:
syntax = "v1"
type registerReq {
Username string `form:"username"`
Password string `form:"password"`
}
@server(
group: identity
)
service gateway {
@handler register
post /douyin/user/register (registerReq)
}
Identity 服务:
syntax = "proto3";
package identity;
option go_package = "./identity";
message Resp {
int32 status_code = 1;
string status_msg = 2;
}
message registerReq {
string username = 1;
string password = 2;
}
message registerResp {
Resp response = 1;
int64 user_id = 2;
string token = 3;
}
service identity {
rpc register(registerReq) returns (registerResp);
}
遇到的问题
在 rpc 服务中,我使用了自己定义的错误
type Error interface {
error
Error() string
}
type RespError struct {
Code int32 `json:"code"`
Msg string `json:"msg"`
}
func (e *RespError) Error() string {
return fmt.Sprintf("err_code: %d, err_msg: %s", e.Code, e.Msg)
}
当遇到错误时,便会返回rpcResponse{}, *RespError
由于 Gateway 对于前端要求输出格式统一,默认情况下,Gateway 在接受到 rpc服务 返回的错误时,会直接输出类似 rpc error:: code = Unknow desc = code: xxx ,msg: xxx,Gateway 无法很好的对其进行解析。
解决方案
go-zero 的文档并不全,一开始我是跟着文档中所描述,在 Gateway 中使用 httpx.SetErrorHandlerCtx对其错误进行拦截,达到自定义错误的方式。
但 rpc服务 返回的 error 比较奇怪,在尝试过使用 error.As 对其进行转换后,也无法获取定义的 Code 与 Msg.
最终,在阅读了下 go-zero 的源码后,发现要求返回的错误,似乎是 Grpc 中的 status.Status. 我们可以通过 status.Error() 生成错误。 这样在 Gateway 中便可以通过 status.FromError() 对其进行解析。