文件格式
go-zero文件夹如如下所示
├─.idea
├─chat
│ ├─api
│ └─rpc
├─comment
│ ├─api
│ └─rpc
├─count
│ ├─api
│ ├─model
│ └─rpc
│ ├─count
│ ├─countclient
│ ├─etc
│ ├─internal
│ │ ├─config
│ │ ├─dao
│ │ ├─logic
│ └─~
│ └─logs
│ └─csp
└─video
├─api
└─rpc
每一个微服务起一个文件夹,每一个文件夹里包含api,model,rpc等等文件夹
rpc
生成proto文档
goctl rpc template -o add.proto
生成rpc架构
goctl rpc protoc add.proto --go_out=. --go-grpc_out=. --zrpc_out=.
yaml
#rpc的名字和监听的端口
Name: user.rpc
ListenOn: 0.0.0.0:8090
# 测试模式下需要指定Mode:dev,不然rpc无法注册
Mode: dev
# etcd注册rpc,- 表示数组
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc
logic层写业务逻辑
func (l *RegistLogic) Regist(in *user.RegistReq) (*user.RegistResp, error) {
// todo: add your logic here and delete this line
res := &user.RegistResp{}
//限流控制
e, b := sentinel.Entry("user-limit", sentinel.WithTrafficType(base.Inbound))
if b != nil {
fmt.Println("被限流了")
return res, errors.New(b.Error())
}
fmt.Println("流量放行")
defer e.Exit()
exit, err := dao.UserExit(libraries.DB(), in.UserName)
if err != nil {
return res, err
}
if exit {
return res, nil
}
user := &model.User{
Id: in.UserId,
Name: in.UserName,
PassWord: in.PassWord}
err = dao.CreateUser(libraries.DB(), user)
if err != nil {
return res, err
}
token, err := libraries.GetJwtToken(l.svcCtx.Config.JWT.AccessSecret, l.svcCtx.Config.JWT.AccessExpire, in.UserId, in.UserName)
if err != nil {
return res, err
}
res.UserId = in.UserId
res.Token = token
return res, nil
}
api
生成api文件
#进入api文件夹后执行该命令
goctl api -o relationship.api
修改api文件
type loginReq {
// TODO: add members here and delete this comment
Name string `form:"username"`
Password string `form:"password"`
}
type loginResp {
// TODO: add members here and delete this comment
StatusCode int64 `json:"status_code"`
StatusMsg string `json:"status_msg"`
UserId int64 `json:"user_id"`
Token string `json:"token"`
}
type JwtToken {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
@server(
prefix: /douyin/user
)
service user-api {
@handler CreateUser // TODO: set handler name and delete this comment
post /register (registReq) returns (registResp)
@handler Login // TODO: set handler name and delete this comment
post /login (loginReq) returns (loginResp)
}
@server(
jwt: Auth
)
service user-api {
@handler userInfo
get /user/info () returns (UserReply)
}
先定义req和resp,再定义@service,最后定义 service
@service是注册中间件和前缀的地方
service是注册路由和定义请求方法的地方
值得注意的是,go-zero的分组机制不是很好,所以每次分组的时候,需要重写一个@server和service
写完后执行
goctl api go -api user.api -dir .
已经生成过的,再次执行不会重新执行;后来新增的内容可以执行
注册rpcclinet
server包里,将rpcclient注册到里面
type ServiceContext struct {
Config config.Config
UserRpcClient userclient.User
CountRpcClient countclient.Count
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
UserRpcClient: userclient.NewUser(zrpc.MustNewClient(c.UserRpcConf)),
CountRpcClient: countclient.NewCount(zrpc.MustNewClient(c.CountRpcConf)),
}
}
conf里读取yaml文件的配置
type Config struct {
rest.RestConf
UserRpcConf zrpc.RpcClientConf
CountRpcConf zrpc.RpcClientConf
Auth struct {
AccessSecret string
AccessExpire int64
}
}
yaml写配置文件
#api的名字和监听的ip端口
Name: user-api
Host: 0.0.0.0
Port: 8888
#RPC的的配置文件和相应的IP
CountRpcConf:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: count.rpc
logic层写业务逻辑
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) {
// todo: add your logic here and delete this line
md5Password := libraries.Md5(req.Password)
loginResp, err := l.svcCtx.UserRpcClient.Login(l.ctx, &user.LoginReq{
UserName: req.Name,
PassWord: md5Password,
})
if err != nil {
return resp, err
}
resp.UserId = loginResp.UserId
resp.Token = loginResp.Token
return resp, nil
}