这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
一、本堂课重点内容:
- api目录讲解
- 作用详解
- 个人小结
本文通过项目来进行案例讲解。
二、api目录讲解
顾名思义,api-gateway是网关层设计,是进行路由分发、鉴权、限流等中间层处理的服务部分,该部分结构如下所示。上文提到,我们的网关是基于Hertz进行开发的,因此结构符合Hertz项目结构。分别包含biz、middlewares、router、主函数以及proto文件,下面将一一进行详解。
├── biz # 业务逻辑
│ ├── handler # 前置处理,RPC 调用,返回结果
│ │ ├── UserCommPb
│ │ ├── userFavoPb
│ │ ├── userInfoPb
│ │ ├── userRelationPb
│ │ └── videoOperatorPb
│ ├── model # Hertz 生成 Kitex 调用客户端
│ └── rpcClient # 单例模式 Client
├── main.go
├── middlewares # 自定义中间件
│ ├── accessLog.go
│ ├── auth.go
│ └── limit.go
└── router # 路由
└── app.go
三、作用详解
-
proto文件
- 代码生成器基于protoc文件进行文件生成,一个proto文件代表一个微服务,因为我们的模块是分成四个大模块,因此事四个proto文件,分别是comment、userFavo、userInfo以及VideoOperaor。前置环境需要提前安装,hz代码生成器命令如下所示
-
// new文件结构 hz new --mod=项目名 --idl=proto或者thrift文件
-
biz(业务逻辑部分,本层是通过Hertz代码进行生成的)
- 如上图所示,分为handler、model、rpcClient部分,区别于自动生成的,本项目结合项目特色进行改造,去掉了生成的router,而改用调用rpc服务的客户端生成。
- handler:它是与App相对应的接口,因此一般来说,有几个接口,handler的函数一般就有几个。以用户信息模块的登陆接口为例,在handler需要完成格式的输出,将rpc的结构体转化成满足文档接口的要求。
// 用户信息的Login登陆
func LoginMethod(ctx context.Context, c *app.RequestContext) {
var req LoginReq
// 1.绑定参数
err := c.BindAndValidate(&req)
if err != nil {
respErr := &userInfoPb.LoginResp{StatusMsg: err.Error(), StatusCode: 1}
c.JSON(200, respErr)
return
}
// 2.调用rpc
resp, err := rpcClient.UserInfo.Login(ctx, &userInfoPb.LoginReq{
UserName: req.UserName,
Password: req.Password,
})
// 3.异常处理
if err != nil {
respErr := &userInfoPb.LoginResp{StatusMsg: err.Error(), StatusCode: 1}
c.JSON(200, respErr)
return
}
// 4.正常返回,将格式转成客户端能解析的json格式
hlog.Info("resp", resp)
c.JSON(200, utils.H{
"status_code": resp.GetStatusCode(),
"status_msg": resp.GetStatusMsg(),
"user_id": resp.GetUserId(),
"token": resp.GetToken()},
)
return
}
- model:handler函数的参数结构体,这部分是通过protoc生成的。
- rpcClient:rpc客户端生成,是代码抽象的体现,同时在这里实现服务发现
// rpc客户端生成
func init() {
// nacos服务发现
c, err := userinfo.NewClient("userInfoImpl", client.WithResolver(resolver.NewNacosResolver(nacos.Cli)))
if err != nil {
panic(err)
}
UserInfo = c
}
四、个人小结
本文介绍本次字节项目中个人负责的api-gateway部分