对于咱们快速了解和将 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
安装 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-L
。goctl
的意思是不要被代码控制,而是要去控制它。其中的 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 部分的接口
需求
- 例如有一个订单场景,我们需要查询某个租户的地址
- 另外在租户系统这边,需要添加租户
这个时候,我们知道,对于用户来说,访问的自然是 http 接口,那对于查询具体的租户信息,自然是内部微服务来进行处理
一般来说,HTTP 接口对外,RPC接口对内
正如这样
先来定义 rpc 接口
- 咱们先建立项目目录:
mkdir my_test_demo/mymall -p cd my_test_demo go mod init my_test_demo
- 创建租户的 rpc 模块
mkdir mymall/tenant/rpc -p cd mymall/tenant/rpc
- 编写 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); }
- 使用 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 接口
- 创建订单的 api 模块
回到项目根目录 my_test_demo mkdir mymall/order/api -p cd mymall/order/api
- 编写 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) }
- 使用 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 部分自动生成的部分就完成了
数据库
- 创建 model 目录
回到项目根目录 my_test_demo mkdir mymall/tenant/rpc/protoc/model -p cd mymall/tenant/rpc/protoc/model
- 编写 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;
- 向 数据表中插入一条数据,为后续做准备
insert into tenant_info values("ceshiid", "约等于公司", "修罗道哦");
- 使用 goctl 工具生成 model 部分的代码
goctl model mysql ddl -src tenant.sql -dir .
可以看到 goctl 给我们生成的 model 代码是这个样子的
├── tenantinfomodel_gen.go ├── tenantinfomodel.go ├── tenant.sql └── vars.go
填充逻辑层和配置
- 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 ,去掉多导入的包
- 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 操作 rpc
cd mymall/tenant/rpc go mod tidy go run tenant.go
- 打开终端 2 操作 api
cd mymall/order/api go run order.go
- 打开终端 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 生成的,我们需要的就如下几件事
- 基本 api ,proto ,sql 的定义
- 修改 xml 配置 , 和 config.go 的配置
- 修改 svc 下面的关联上下线文
- 修改 logic 层,填上自己的逻辑
- 如果对于数据库生成默认的方法,不够满足业务场景,我们也可以依葫芦画瓢实现自己的方法,进行使用即可
另外,我们看到咱们定义的 proto 还有一个 addTenant 方法,实际上我们去实现的话,可以在 mymall/tenant 下添加api目录,按照上述 api 的添加方式来进行处理即可,感兴趣的朋友可以来尝试一波哦
如果想看源码的,欢迎访问地址:https://github.com/qingconglaixueit/my_test_Demo
感谢阅读,欢迎交流,点个赞,关注一波 再走吧
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~
可以进入地址进行体验和学习:https://xxetb.xet.tech/s/3lucCI