go-zero 负载均衡
在 go-zero 中,负载均衡算法主要应用在 gRPC 的客户端,用于将请求分发给不同的 gRPC 服务端,采用的是 P2C 算法。 详情见 p2c.go
go-zero 负载均衡
在 go-zero 中,负载均衡算法主要应用在 gRPC 的客户端,用于将请求分发给不同的 gRPC 服务端,采用的是 P2C 算法。 详情见 p2c.go
go-zero内置了断路器
在 go-zero 中,开发者不需要对请求单独进行熔断处理,该功能已经集成到了框架中,因此开发者无需关心。
HTTP 以请求方法+路由作为统计维度,用 HTTP 状态码 500 作为错误采集指标进行统计,详情可参考 breakerhandler.go
gRPC 客户端以 rpc 方法名作为统计维度,用 grpc 的错误码为 codes.DeadlineExceeded
, codes.Internal
, codes.Unavailable
, codes.DataLoss
, codes.Unimplemented
作为错误采集指标进行统计,详情可参考 breakerinterceptor.go
gRPC 服务端以 rpc 方法名称作为统计维度,用 grpc 的错误作为错误采集指标进行统计,详情可参考 breakerinterceptor.go
go-zero:goctl从sql生成go代码
mysql 代码生成支持从 sql 文件和数据库链接生成, 且支持生成带缓存逻辑代码。
mysql 生成的代码内容有数据表对应的 golang 结构体、CURD 操作方法,缓存逻辑等信息,更多详细的数据库代码生成可参考指南 goctl model
首先执行如下指令将示例 sql 文件存储到本地的 user.sql
文件中。
CREATE TABLE user (
id bigint AUTO_INCREMENT,
name varchar(255) NULL COMMENT 'The username',
password varchar(255) NOT NULL DEFAULT '' COMMENT 'The user password',
mobile varchar(255) NOT NULL DEFAULT '' COMMENT 'The mobile phone number',
gender char(10) NOT NULL DEFAULT 'male' COMMENT 'gender,male|female|unknown',
nickname varchar(255) NULL DEFAULT '' COMMENT 'The nickname',
type tinyint(1) NULL DEFAULT 0 COMMENT 'The user type, 0:normal,1:vip, for test golang keyword',
create_at timestamp NULL,
update_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE mobile_index (mobile),
UNIQUE name_index (name),
PRIMARY KEY (id)
) ENGINE = InnoDB COLLATE utf8mb4_general_ci COMMENT 'user table';
新建工作空间和目录工程
$ mkdir -p ~/workspace/model/mysql
将上文中存储的 user.sql
文件移动到 ~/workspace/model/mysql
目录下
生成 model 代码
$ cd ~/workspace/model/mysql
$ goctl model mysql ddl --src user.sql --dir .
Done.
当你看到 Done.
输出则代表生成成功了,接下来我们来看一下生成的代码内容:
# 列出当前目录下的文件
$ ls
user.sql usermodel.go usermodel_gen.go vars.go
# 查看目录树
$ tree
.
├── user.sql
├── usermodel.go
├── usermodel_gen.go
└── vars.go
0 directories, 4 files
go-zero rest api 路由前缀例子
在 go-zero 中,我们通过 api 语言来声明 HTTP 服务,然后通过 goctl 生成 HTTP 服务代码,在之前我们系统性的介绍了 API 规范。
在 HTTP 服务开发中,路由前缀需求是非常常见的,比如我们通过路由来区分版本,或者通过路由来区分不同的服务,这些都是非常常见的需求。
假设我们有一个用户服务,我们需要通过路由来区分不同的版本,我们可以通过 api 语言来声明路由前缀:
https://example.com/v1/users
https://example.com/v2/users
在上文路由中,我们通过版本 v1
和 v2
来区分了 /users
路由,我们可以通过 api 语言来声明路由前缀:
syntax = "v1"
type UserV1 {
Name string `json:"name"`
}
type UserV2 {
Name string `json:"name"`
}
@server (
prefix: /v1
)
service user-api {
@handler usersv1
get /users returns ([]UserV1)
}
@server (
prefix: /v2
)
service user-api {
@handler usersv2
get /users returns ([]UserV2)
}
在上文中,我们通过在 @server
中来通过 prefix
关键字声明了路由前缀,然后通过 @handler
来声明了路由处理函数,这样我们就可以通过路由前缀来区分不同的版本了。
下面简单看一下生成的路由代码:
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/users",
Handler: usersv1Handler(serverCtx),
},
},
rest.WithPrefix("/v1"),
)
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/users",
Handler: usersv2Handler(serverCtx),
},
},
rest.WithPrefix("/v2"),
)
}
在上文中,我们可以看到,我们声明的 prefix
其实在生成代码后通过 rest.WithPrefix
来声明了路由前缀,这样我们就可以通过路由前缀来区分不同的版本了。
go-zero 路由规则
在 go-zero 中,我们通过 api 语言来声明 HTTP 服务,然后通过 goctl 生成 HTTP 服务代码,在之前我们系统性的介绍了 API 规范。
在 api 描述语言中,有特定的路由规则,这些路由规则并非和 HTTP 的路由规则完全引用,接下来我们来看一下 api 描述语言中的路由规则吧。
在 api 描述语言中,路由需要满足如下规则
/
开头/
分隔:
,但是 :
必须是路由节点的第一个字符,:
后面的节点值必须要在结请求体中有 path
tag 声明,用于接收路由参数,详细规则可参考 路由参数。goctl 1.5.1
支持,可参考 新版 API 解析器使用)、下划线、中划线路由示例:
syntax = "v1"
type DemoPath3Req {
Id int64 `path:"id"`
}
type DemoPath4Req {
Id int64 `path:"id"`
Name string `path:"name"`
}
type DemoPath5Req {
Id int64 `path:"id"`
Name string `path:"name"`
Age int `path:"age"`
}
type DemoReq {}
type DemoResp {}
service Demo {
// 示例路由 /foo
@handler demoPath1
get /foo (DemoReq) returns (DemoResp)
// 示例路由 /foo/bar
@handler demoPath2
get /foo/bar (DemoReq) returns (DemoResp)
// 示例路由 /foo/bar/:id,其中 id 为请求体中的字段
@handler demoPath3
get /foo/bar/:id (DemoPath3Req) returns (DemoResp)
// 示例路由 /foo/bar/:id/:name,其中 id,name 为请求体中的字段
@handler demoPath4
get /foo/bar/:id/:name (DemoPath4Req) returns (DemoResp)
// 示例路由 /foo/bar/:id/:name/:age,其中 id,name,age 为请求体中的字段
@handler demoPath5
get /foo/bar/:id/:name/:age (DemoPath5Req) returns (DemoResp)
// 示例路由 /foo/bar/baz-qux
@handler demoPath6
get /foo/bar/baz-qux (DemoReq) returns (DemoResp)
// 示例路由 /foo/bar_baz/123(goctl 1.5.1 支持)
@handler demoPath7
get /foo/bar_baz/123 (DemoReq) returns (DemoResp)
}
go-zero组件分类