关于go-zero:微服务框架-gozero-快速实战

36次阅读

共计 7468 个字符,预计需要花费 19 分钟才能阅读完成。

对于咱们疾速理解和将 go-zero 应用起来,咱们须要具备如下能力

  • 根本的环境装置和看文档的能力

<!—->

  • Golang 的基本知识

<!—->

  • Protobuf 的基本知识

<!—->

  • web,rpc 的基本知识

<!—->

  • 根本的 mysql 常识

其实这些能力,很根底,不须要如许深刻,只须要你有所理解,这样至多对于咱们去看 go-zero 波及的知识点就不会那么费劲儿

本文分为如下 4 个局部来 别离介绍和疾速实战微服务框架 go-zero

  • 微服务框架 go-zero 的根本介绍

<!—->

  • go-zero 的环境搭建

<!—->

  • go-zero 的疾速实战 rpc api ,model 局部

微服务框架 go-zero 的根本介绍

go-zero 是一个集成了各种工程实际的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,禁受了充沛的实战测验。

go-zero 中的 api,rpc,数据库等波及的代码,都能够给咱们一键生成,无需消耗咱们什么精力

只须要在生成的代码中填入本人的配置以及逻辑即可,咱们应用 go-zero 能够轻松做到如下成果:

  • 轻松取得撑持千万日活服务的稳定性

<!—->

  • 内建级联超时管制、限流、自适应熔断、自适应降载等微服务治理能力,无需配置和额定代码

<!—->

  • 微服务治理中间件可无缝集成到其它现有框架应用

<!—->

  • 极简的 API 形容,一键生成各端代码

<!—->

  • 主动校验客户端申请参数合法性

<!—->

  • 大量微服务治理和并发工具包

对于咱们开发微服务堪称是极大的进步了开发效率和品质,缩小了开发者的心智累赘

go-zero 官网提供了一张架构图

从架构图咱们晓得,上述的各种成果离不开架构图中的每一个模块,本文先展现如下性能的利用:

  • HTTP 协定

<!—->

  • gRPC 协定

<!—->

  • 日志记录

<!—->

  • 链路追踪

<!—->

  • 数据库

<!—->

  • ETCD 服务发现

<!—->

看到 go-zero 有这么多益处,架构图也十分清晰,是不是有点急不可待了呢

go-zero 的环境搭建

不焦急,工欲善其事必先利其器,咱们能将 go-zero 玩起来的先决条件是搭建根本的环境,为了接下来的实战做铺垫,咱们须要搭建如下几个工具

  • 有一台根本的云服务器最好,虚拟机也没有问题

<!—->

  • 装置 etcd,mysql

<!—->

  • 装置 protoc 工具

<!—->

  • 装置 goctl 工具

装置 etcd,mysql

etcd

ETCD_VER=v3.5.0

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version

装置结束后,能够应用 etcdctl version 查看工具的版本

如果想理解 etcd 的根本应用,咱们不焦急,本次文章应用不多,无需太过关注 etcd 的细节

mysql

Linux(centos)下 Mysql 环境装置

装置 protoc 工具

go get -u github.com/golang/protobuf/protoc-gen-go@v1.3.2
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protoc-3.14.0-linux-x86_64.zip
unzip protoc-3.14.0-linux-x86_64.zip
mv bin/protoc /usr/local/bin/

装置结束后,能够应用 protoc –version 查看工具的版本

装置 goctl 工具

goctl 读作 go control,不要读成 go C-T-Lgoctl 的意思是不要被代码管制,而是要去管制它。其中的 go 不是指 golang

装置咱们 golang 的时候,间接装置 go 1.16 版本以上的,而后执行如下命令即可

GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest

装置结束后,能够应用 goctl –version 查看工具的版本

go-zero 的疾速实战

环境装置结束之后,咱们就能够来进行实战了,方才有说到 go-zero 是一个集成了各种工程实际的 web 和 rpc 框架,那么咱们就能够来设计 web 局部的接口和 rpc 局部的接口

需要

  1. 例如有一个订单场景,咱们须要查问某个租户的地址

<!—->

  1. 另外在租户零碎这边,须要增加租户

这个时候,咱们晓得,对于用户来说,拜访的天然是 http 接口,那对于查问具体的租户信息,天然是外部微服务来进行解决

一般来说,HTTP 接口对外, RPC 接口对内

正如这样

先来定义 rpc 接口

  1. 咱们先建设我的项目目录:
mkdir my_test_demo/mymall -p
cd my_test_demo
go mod init my_test_demo
  1. 创立租户的 rpc 模块
mkdir mymall/tenant/rpc -p
cd mymall/tenant/rpc
  1. 编写 proto 文件

提供两个 rpc 接口

  • getTenant

    • 获取租户信息

<!—->

  • addTenant

    • 增加租户

tenant.proto

syntax = "proto3";

package tenant;

option go_package = "./tenant";

message TidReq {string name = 1;}
message TenantRsp {
    // 租户名称
    string id = 1;
    // 租户名称
    string name = 2;
    // 用户地址
    string addr = 3;
}

message addTenantReq {
    // 租户名称
    string name = 1;
    // 用户地址
    string addr = 2;
}


message addTenantRsp {
    // 租户 id
    string id = 1;
}

service Tenant {rpc getTenant(TidReq) returns(TenantRsp);
    rpc addTenant(addTenantReq) returns(addTenantRsp);
}
  1. 应用 goctl 工具生成 golang 代码
goctl rpc protoc tenant.proto --go_out=./protoc --go-grpc_out=./protoc --zrpc_out=.

能够看到 goctl 工具给咱们生成的代码目录是这样的

├── etc
│   └── tenant.yaml
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   ├── addtenantlogic.go
│   │   └── gettenantlogic.go
│   ├── server
│   │   └── tenantserver.go
│   └── svc
│       └── servicecontext.go
├── protoc
│   └── tenant
│       ├── tenant_grpc.pb.go
│       └── tenant.pb.go
├── tenant
│   └── tenant.go
├── tenant.go
└── tenant.proto

这个时候,对于 rpc 主动生成的局部就实现了

定义 api 接口

  1. 创立订单的 api 模块
回到我的项目根目录 my_test_demo
mkdir mymall/order/api -p
cd mymall/order/api
  1. 编写 api

定义一个 Get 办法,url 为 / api /order/get/:name 的 http 接口

order.api

type (
        OrderReq {Name string `path:"name"`}

        OrderReply {
                Id   string `json:"id"`
                Name string `json:"name"`
                Addr string `json:"addr"`
        }
)
service order {
        @handler getOrder
        get /api/order/get/:name (OrderReq) returns (OrderReply)
}
  1. 应用 goctl 工具生成代码
goctl api go -api order.api  -dir .

这个时候,咱们能够看到,goctl 工具给咱们生成的目录构造和代码是这个样子的

├── etc
│   └── order.yaml
├── internal
│   ├── config
│   │   └── config.go
│   ├── handler
│   │   ├── getorderhandler.go
│   │   └── routes.go
│   ├── logic
│   │   └── getorderlogic.go
│   ├── svc
│   │   └── servicecontext.go
│   └── types
│       └── types.go
├── order.api
└── order.go

同样的,web 局部主动生成的局部就实现了

数据库

  1. 创立 model 目录
回到我的项目根目录  my_test_demo
mkdir mymall/tenant/rpc/protoc/model -p
cd mymall/tenant/rpc/protoc/model
  1. 编写 sql
  • 先在 linux 外面进入 mysql,创立一个数据库 test_demo

<!—->

  • 再创立一张表,表的字段如上面 sql 文件所述

tenant.sql

CREATE TABLE `tenant_info`
(`id` varchar(255) NOT NULL COMMENT 'tenant id',
  `name` varchar(255) NOT NULL COMMENT 'tenant name',
  `addr` varchar(255) NOT NULL COMMENT 'tenant addr',
  PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  1. 向 数据表中插入一条数据,为后续做筹备
insert into tenant_info values("ceshiid", "约等于公司", "修罗道哦");
  1. 应用 goctl 工具生成 model 局部的代码
goctl model mysql ddl -src tenant.sql -dir .

能够看到 goctl 给咱们生成的 model 代码是这个样子的

├── tenantinfomodel_gen.go
├── tenantinfomodel.go
├── tenant.sql
└── vars.go

填充逻辑层和配置

  1. Api 局部
  • 批改 mymall/order/api/etc/order.yaml,加上 etcd 的配置,咱们配置的 rpc 的 key 是 tenant.rpc
Name: order
Host: 0.0.0.0
Port: 9998
TenantRpc:
  Etcd:
    Hosts:
      - 127.0.0.1:2379
    Key: tenant.rpc
  • 批改 ymall/order/api/internal/config/config.go,Config struct 中加上 rpc 的配置

    • TenantRpc zrpc.RpcClientConf
  • 批改 mymall/order/api/internal/svc/servicecontext.go,加上 rpc 的上下文

    • TenantRpc tenant.Tenant
    • TenantRpc:tenant.NewTenant(zrpc.MustNewClient(c.TenantRpc)),
  • 批改 mymall/order/api/internal/logic/getorderlogic.go,对逻辑层加上咱们自定义的逻辑,调用 rpc 的接口获取租户信息
func (l *GetOrderLogic) GetOrder(req *types.OrderReq) (resp *types.OrderReply, err error) {
   // todo: add your logic here and delete this line
rsp , err:=l.svcCtx.TenantRpc.GetTenant(l.ctx, &tenant.TidReq{Name: req.Name})
   if err != nil{return nil,err}
   return &types.OrderReply{
      Id: rsp.Id,
      Name: rsp.Name,
      Addr: rsp.Addr,
   },nil

}

  • 批改 mymall/order/api/internal/handler/getorderhandler.go,去掉多导入的包
  1. Rpc 局部
  • 批改 mymall/tenant/rpc/etc/tenant.yaml,加上数据源和数据表的配置
Name: tenant.rpc
ListenOn: 127.0.0.1:8080
Etcd:
  Hosts:
  - 127.0.0.1:2379
  Key: tenant.rpc

DataSource: root:123456@tcp(localhost:3306)/test_demo
Table: tenant_info
  • 批改 mymall/tenant/rpc/internal/config/config.go

    • DataSource string
    • Table string
  • 批改 mymall/tenant/rpc/internal/svc/servicecontext.go,增加对于 mysql 的上下文

    • Model model.TenantInfoModel
    • Model:model.NewTenantInfoModel(sqlx.NewMysql(c.DataSource)),

<!—->

  • 批改 mymall/tenant/rpc/protoc/model/tenantinfomodel_gen.go,新增一个数据库的办法 FindOneByName(这个是依据业务本身来抉择是否要加)

    • FindOneByName(ctx context.Context, name string) (*TenantInfo, error)
func (m *defaultTenantInfoModel) FindOneByName(ctx context.Context, name string) (*TenantInfo, error) {query := fmt.Sprintf("select %s from %s where `name` = ? limit 1", tenantInfoRows, m.table)
   var resp TenantInfo
   err := m.conn.QueryRowCtx(ctx, &resp, query, name)
   switch err {
   case nil:
      return &resp, nil
   case sqlc.ErrNotFound:
      return nil, ErrNotFound
   default:
      return nil, err
   }
}

  • 批改 mymall/tenant/rpc/internal/logic/gettenantlogic.go 填充 GetTenant 的逻辑

成果验证

  1. 关上终端 1 操作 rpc
cd mymall/tenant/rpc
go mod tidy
go run tenant.go
  1. 关上终端 2 操作 api
cd mymall/order/api
go run order.go
  1. 关上终端 3 操作 curl

咱们能够先应用 etcdctl 查看一下 tenant.rpc 是否存在

etcdctl get tenant.rpc --prefix

再应用 curl 来申请 api 的接口

curl -i "http://localhost:9998/api/order/get/ 约等于公司"

Api 的日志为

Rpc 的日志

通过上述日志咱们晓得,对于 api 的申请日志,mysql 的日志,rpc 的日志,咱们都能看到 trace 这个字段,实际上就是通过这个字段来进行链路跟踪的,仔细的敌人就能够看到,从 api,到 rpc,到 mysql 这个 trace 字段的值都是同一个,阐明这是同一条调用链上的

其余的细节,咱们后续再聊

总结

至此,咱们理解了 go-zero 微服务框架,疾速实战了一个简略的 demo,这里咱们理论能够体验到,对于 api,rpc,或者是 model 层,绝大部分的代码都是 goctl 生成的,咱们须要的就如下几件事

  1. 根本 api,proto,sql 的定义

<!—->

  1. 批改 xml 配置,和 config.go 的配置

<!—->

  1. 批改 svc 上面的关联高低线文

<!—->

  1. 批改 logic 层,填上本人的逻辑

<!—->

  1. 如果对于数据库生成默认的办法,不够满足业务场景,咱们也能够依葫芦画瓢实现本人的办法,进行应用即可

另外,咱们看到咱们定义的 proto 还有一个 addTenant 办法,实际上咱们去实现的话,能够在 mymall/tenant 下增加 api 目录,依照上述 api 的增加形式来进行解决即可,感兴趣的敌人能够来尝试一波哦

如果想看源码的,欢送拜访地址:https://github.com/qingconglaixueit/my_test_Demo

感激浏览,欢送交换,点个赞,关注一波 再走吧

欢送点赞,关注,珍藏

敌人们,你的反对和激励,是我保持分享,提高质量的能源

好了,本次就到这里

技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。

我是 阿兵云原生,欢送点赞关注珍藏,下次见~

正文完
 0