golang微服务之go-zero零基础实战

golang微服务之go-zero零基础实战

1. 环境准备

  1. mysql
    提供rpc服务接口后端交互存储
  2. etcd
    提供rpc服务注册与发现

2. 文件结构

image

rpc服务接口:
1. 用户登录
2. 用户创建
3. 查询用户信息

api服务接口:
1. 用户登录
2. 用户创建
3. 查询用户信息

3. 搭建步骤

1. 搭建rpc服务

  1. 创建rpc目录
  2. 在rpc目录下创建proto文件,user.proto
syntax = "proto3";

package user;

option go_package="./user";

message UserInfoRequest{
    uint32 id = 1;
}

message UserInfoResponse{
    uint32 id = 1;
    string username = 2;
    bool gender = 3;
}

message UserCreateRequest{
    string username = 1;
    string password = 2;
    bool gender = 3;
}

message UserCreateResponse{
    uint32 id = 1;
    string err = 2;
}

message UserLoginRequest{
    string username = 1;
    string password = 2;
}

message UserLoginResponse{
    bool success = 1;
    uint32 id = 2;
}

service user{
    rpc UserInfo(UserInfoRequest)returns(UserInfoResponse);
    rpc UserCreate(UserCreateRequest)returns(UserCreateResponse);
    rpc UserLogin(UserLoginRequest)returns(UserLoginResponse);
}

// goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.

此处,rpc定义 用户登录、用户创建、获取用户信息 ,三个接口以及请求和响应结构体
使用goctl生成代码
goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.

  1. 修改rpc/etc/user.yaml,配置etcd服务器地址、key、mysql连接地址
Name: user.rpc
ListenOn: 0.0.0.0:8080
Etcd:
  Hosts:
  - 10.100.11.111:2379
  Key: user.rpc
  
Mysql:
  DataSource: root:123456@tcp(10.100.11.111:3306)/db3?parseTime=true
  1. 修改rpc/internal/config/config.go,添加mysql配置项解析
type Config struct {
	zrpc.RpcServerConf
	Mysql struct{
		DataSource string
	}
}
  1. 修改rpc/internal/svc/servicecontext.go,为svc添加DB服务依赖
type ServiceContext struct {
	Config config.Config
	DB  *gorm.DB
}

func NewServiceContext(c config.Config) *ServiceContext {
	db := initgorm.InitGorm(c.Mysql.DataSource)
	return &ServiceContext{
		Config: c,
		DB: db,
	}
}

init_gorm:

func InitGorm(MysqlDataSource string) *gorm.DB{
	db, err := gorm.Open(mysql.Open(MysqlDataSource), &gorm.Config{})
	if err != nil {
		panic("connect fail")
	}else{
		fmt.Println("connect success")
	}
	db.AutoMigrate(&models.UserModel{})
	return db
}
  1. 创建用户model,供数据库使用,修改rpc/models/user_model.go
type UserModel struct{
	gorm.Model
	Username string `gorm:"size:32" json:"user"`
	Password string `gorm:"size:64" json:"password"`
	Gender bool `gorm:"size:64" json:"gender"`
}
  1. 编写logic,用户登录、创建、获取信息的逻辑部分,数据库交互
    用户登录logic:
	var userInfo models.UserModel
	err := l.svcCtx.DB.Where("username = ? and password = ?", in.Username, in.Password).First(&userInfo).Error
	if err != nil {
		return &user.UserLoginResponse{
			Success: false,
		}, err
	}
	return &user.UserLoginResponse{
		Success: true,
		Id: uint32(userInfo.ID),
	}, nil

添加用户logic:

	var model models.UserModel
	pd = new(user.UserCreateResponse)
	err = l.svcCtx.DB.Take(&model, "username = ?", in.Username).Error
	if err == nil {
		pd.Err = "user exist"
		return
	}
	model = models.UserModel{
		Username: in.Username,
		Password: in.Password,
		Gender:   in.Gender,
	}
	err = l.svcCtx.DB.Create(&model).Error
	if err != nil {
		logx.Error(err)
		pd.Err = err.Error()
		err = nil
		return
	}
	fmt.Println(model.ID)
	pd.Id = uint32(model.ID)
	return &user.UserCreateResponse{}, nil

查询用户logic

	var userInfo models.UserModel
	err := l.svcCtx.DB.Take(&userInfo, in.Id).Error
	if err != nil {
		return nil, errors.New("user not exist")
	}
	return &user.UserInfoResponse{
		Id:       uint32(userInfo.ID),
		Username: userInfo.Username,
		Gender: userInfo.Gender,
	}, nil

至此,rpc服务三个接口编写完成,可通过apifox调用rpc接口验证

2. api服务搭建

  1. 新建api目录、
  2. 新建user.api,api文件,编辑三个接口的定义、请求及响应结构体
type UserCreateRequest {
	Username string `json:"username"`
	Password string `json:"password"`
	Gender   bool   `json:"gender"`
}

type UserInfoRequest {
	Id uint `path:"id"`
}

type UserInfoResponse {
	Id       uint   `json:"id"`
	Username string `json:"username"`
	Gender   bool   `json:"gender"`
}

@server (
	prefix: /api/users
	jwt:    Auth
)
service users {
	@handler userCreate
	post / (UserCreateRequest) returns (string)

	@handler userInfo
	get /info/:id (UserInfoRequest) returns (UserInfoResponse)
}

type LoginRequest {
	Username string `json:"username"`
	Password string `json:"password"`
}

@server (
	prefix: /api/users
)
service users {
	@handler login
	post /login (LoginRequest) returns (string)
}

// goctl api go -api user.api -dir .

  1. 生成api服务文件
    goctl api go -api user.api -dir .

  2. 修改api/etc/users.yaml,配置jwt auth及rpc服务地址、key相关配置

Name: users
Host: 0.0.0.0
Port: 8888
Auth:
  AccessSecret: a123456aaa
  AccessExpire: 86400
UserRpc:
  Etcd:
    Hosts:
    - 10.100.13.120:2379
    Key: user.rpc
  1. 修改api/internal/config/config.yaml,添加userRpc及jwtAuth相关配置解析
type Config struct {
	rest.RestConf
	UserRpc zrpc.RpcClientConf
	Auth struct{
		AccessSecret string
		AccessExpire int64
	}
}
  1. 修改api/internal/svc/servicecontext.go,为svc添加rpc服务依赖
type ServiceContext struct {
	Config config.Config
	UserRpc userclient.User
	
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config: c,
		UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
	}
}
  1. 编写logic,调用rpc服务接口
    用户登录:
	res, err := l.svcCtx.UserRpc.UserLogin(l.ctx, &userclient.UserLoginRequest{
		Username: req.Username,
		Password: req.Password,
	})
	if err != nil {
		return "", errors.New("login fail")
	}
	token, err := jwts.GenToken(&jwts.JwtPayLoad{
		UserID:   uint(res.Id),
		Username: req.Username,
		Role: 1,
	}, l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire)
	if err != nil {
		return "", errors.New("login fail")
	}
	return token, nil

创建用户:

	response, err := l.svcCtx.UserRpc.UserCreate(l.ctx, &user.UserCreateRequest{
		Username: req.Username,
		Password: req.Password,
	})
	if err != nil {
		return "", err
	}
	if response.Err!= ""{
		return "", errors.New(response.Err)
	}
	return

查询用户:

	response, err := l.svcCtx.UserRpc.UserInfo(l.ctx, &user.UserInfoRequest{
		Id: uint32(req.Id),
	})
	if err != nil {
		return nil, err
	}
	return &types.UserInfoResponse{
		Id: uint(response.Id),
		Username: response.Username,
		Gender: response.Gender,
	}, nil

至此,api服务接口搭建完成

4. 启动服务

rpc:
go run user.go

api:
go run users.go

posted @ 2024-05-22 15:49  BrandonV  阅读(243)  评论(0)    收藏  举报