go-zero微服务简单应用

发布日期: 2024-01-09 22:17:06 作者: Stephen 评论: 0

go-zero 是一个集成了各种工程实践的 webrpc 框架。通过弹性设计保障了大并发服务端的稳定性。go-zero 包含极简的API定义和生成工具goctl,可以根据自定义的 apiproto 文件一键生成 go 代码

环境安装

goctl

goctl 是 go-zero 的内置脚手架,是提升开发效率的一大利器,可以一键生成代码、文档、部署 k8s yaml、dockerfile 等。

# go version < 1.16
go get -u github.com/zeromicro/go-zero/tools/goctl@latest
# go version >= 1.16
go install github.com/zeromicro/go-zero/tools/goctl@latest

protoc

protoc 是一个用于生成代码的工具,它可以根据 proto文件生成C++、Java、Python、Go、PHP 等多重语言的代码,而 gRPC 的代码生成还依赖 protoc-gen-goprotoc-gen-go-grpc 插件来配合生成 Go 语言的 gRPC 代码。

goctl env check --install --verbose --force

Etcd

参考《Etcd安装及基本命令

go-zero 微服务简单应用

比如,我们有一个商城系统,需要在订单模块根据 user_id 查询对应用户信息,那么我们的订单系统就需要开启一个 HTTP 服务,用户系统开启一个 gRPC 服务。

mkdir -p ~/work/mall/order
mkdir -p ~/work/mall/user
cd ~/work/mall
go mod init

用户系统

user/user.proto

# vim user/user.proto

syntax = "proto3";

package user;

// protoc-gen-go 版本大于1.4.0,proto文件需要加上go_package,否则无法生成
option go_package = "./user";

message IdRequest {
  int64 id = 1;
}

message UserResponse {
  int64 id = 1;
  string name = 2;
  string gender = 3;
}

service User{
  rpc getUser (IdRequest) returns (UserResponse);
}

生成 gRPC 代码

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

完善用户逻辑代码 user/internal/logic/getuserlogic.go

func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {
    // todo: add your logic here and delete this line

    return &user.UserResponse{
        Id:     in.GetId(),
        Name:   "Hello Zero",
        Gender: "男",
    }, nil
}

订单系统

生成api代码

order/order.api

# vim order/order.api

syntax = "v1"

type OrderRequest {
    Id int64 `path:"id"`
}

type OrderResponse {
    Id         int64  `json:"id"`
    Status     string `json:"status"`
    UserId     int64  `json:"user_id"`
    Username   string `json:"username"`
    UserGender string `json:"user_gender"`
}

service order-api {
    @handler OrderHandler
    get /order/:id (OrderRequest) returns (OrderResponse)
}

生成 api 代码

cd user
goctl api go --api order.api --dir .

配置 Etcd

oder/etc/order-api.yaml

# vim oder/etc/order-api.yaml

UserRpc:
  Etcd:
    Hosts:
      - 127.0.0.1:2379
    Key: user.rpc

order/internal/config/config.go

# vim order/internal/config/config.go

type Config struct {
    rest.RestConf
    UserRpc zrpc.RpcClientConf
}

依赖注入

初始化 UserRPC 客户端

order/internal/svc/servicecontext.go

# vim order/internal/svc/servicecontext.go

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)),
    }
}

完善订单逻辑代码

func (l *OrderInfoLogic) Order(req *types.OrderRequest) (resp *types.OrderResponse, err error) {
    // todo: add your logic here and delete this line

    res := &types.OrderResponse{
        Id:     req.Id,
        Status: "UN_PAY",
        UserId: 88,
    }

    // 调用User RPC服务,查询用户信息
    userResponse, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdRequest{
        Id: res.UserId,
    })
    if err != nil {
        return nil, err
    }
    res.Username = userResponse.Name
    res.UserGender = userResponse.Gender

    return res, nil
}

启动

go mod tidy

# 启动 user rpc 服务
cd user
go run user.go

# 启动 order http 服务,默认监听8080端口
cd ../order
go run order.go

浏览器访问 http://127.0.0.1:8888/order/10086 返回了用户信息表示成功

{
"id": 10086,
"status": "UN_PAY",
"user_id": 88,
"username": "Hello Zero",
"user_gender": "男"
}

快来抢沙发