go-tip
go-zero
是当前处于CNCF孵化中的一个Go
z语言框架项目,在Github上的star数目前达到14.3K。
作为一款起源于国内的项目,go-zero
的中文资料比较齐全,对国内开发者相对友好。但前景如何,还需要进一步的观察。今天我们一起来了解这个项目。
官方文档 - https://go-zero.dev/cn/
Github - https://github.com/zeromicro/zero-doc
go-zero is a web and rpc framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.
官方核心将自己定位为一个 Go语言的web和rpc框架。其余描述内容的意义不大,如稳定的、可伸缩的,更多依赖的是Paas平台与程序自身的设计。
有了前面三个框架的基础,了解go-zero
会相对容易。这次,我将换一个思路讲解,先从官方的示例出发,再回过头来看看这个框架的核心思想。
以下内容,来自go-zero
提供的中文示例 - https://go-zero.dev/cn/shorturl.html
主要安装的二进制工具包括以下三个:
其中第三个是go-zero
自研的。不难看出,go-zero
是强依赖protobuffer生态的。
type (
shortenReq {
url string `form:"url"`
}
shortenResp {
shorten string `json:"shorten"`
}
)
service shorturl-api {
@server(
handler: ShortenHandler
)
get /shorten(shortenReq) returns(shortenResp)
}
这是一套 go-zero
特定的语法。虽说这个语法阅读起来很容易理解,里面有Go语言和protobuffer的影子,但就是一个完全独立的一套方案。
值得注意的是,我们如果要在这个语法中引入各类网关层的特性,如限流参数等,会导致这个语法的学习成本越来越高。
核心为一个protobuffer的定义,如下:
syntax = "proto3";
package transform;
message shortenReq {
string url = 1;
}
message shortenResp {
string shorten = 1;
}
service transformer {
rpc shorten(shortenReq) returns(shortenResp);
}
接下来工具会生成相应的代码,以及会有相关的配置文件可供修改。
由于API Gateway与rpc服务是两个独立的进程,所以需要修改对应的配置(端口等信息),进行打通。
核心代码如下:
func (l *ShortenLogic) Shorten(req types.ShortenReq) (types.ShortenResp, error) {
// 手动代码开始
resp, err := l.svcCtx.Transformer.Shorten(l.ctx, &transformer.ShortenReq{
Url: req.Url,
})
if err != nil {
return types.ShortenResp{}, err
}
return types.ShortenResp{
Shorten: resp.Shorten,
}, nil
// 手动代码结束
}
即新建出一个rpc服务的对象Transformer
,调用对应的方法Shorten
。
关于model层的生成,也就是对MySQL
的CRUD方案,我这里就不专门写了。
我们关注一下最终调用到MySQL
层的代码:
func (l *ShortenLogic) Shorten(in *transform.ShortenReq) (*transform.ShortenResp, error) {
// 手动代码开始,生成短链接
key := hash.Md5Hex([]byte(in.Url))[:6]
_, err := l.svcCtx.Model.Insert(model.Shorturl{
Shorten: key,
Url: in.Url,
})
if err != nil {
return nil, err
}
return &transform.ShortenResp{
Shorten: key,
}, nil
// 手动代码结束
}
有了这么一个实例,我们再回过头来看看整体的架构:
go-zero
go-zero
的架构图包含了五层,但它的核心聚焦于API Gateway与Services这两层。
从框架分层来看,我个人是不太认同这种划分方式。这张图中的架构,更多得是为了体现出go-zero
的两层结构而产出的架构图。尤其是API Gateway这个设计,表现出了团队在Service Mesh上能力的不足、而引入的功能。
目前为止,我们已经一起看了四个不同的微服务框架,也许有同学会觉得我总是在到处挑刺,那么我理想中的微服务框架是怎么样的呢?我来谈谈:
这么聊下来,可能还是有点抽象,我再结合两个例子谈谈这块:
gRPC
的生态生成具体的代码,充分利用middleware(拦截器)的特性实现panic recovery+logging+metrcis等通用的能力;最后一点有部分人会不好理解,以MySQL ORM框架为例,它们在函数中提供的查询方法名是Find/Query/Search等,但对应到SQL的关键词是SELECT,这就对熟悉MySQL的同学来说需要一种思维转变,有一定的成本。更好的方式,那就是ORM里的函数直接使用SELECT这种关键词。
Controller这层的开发量很有限,基本已经由社区提供能力,更应该关注如何能形成一套标准规范;而框架更多的精力应关注在Model这层,它需要大量的、易用的SDK积累,能便捷地对接各类中间件,才能体现出框架的价值。
总体来说,我觉得go-zero
是一个早期云原生环境下的框架,在目前Service Mesh大规模落地后,有大量的特性造成了冲突。从研发体验、维护成本和稳定性角度来看,这部分功能更应该交给跨语言的Service Mesh来解决,而不是编程语言强相关的框架。目前,国内互联网大公司基本不会采用go-zero
,这点占据很大因素。
不过,go-zero
在Model层做了一定的自动化,是一个很值得学习的能力。作为CNCF的项目之一,go-zero
后续是否会有大的转变、更加贴合整个CNCF的氛围,我个人还是非常期待的。