常⻅ web 框架
httprouter
- ⼏乎是所有 Go web 框架的 router 实现的爸爸
- ⼀个简单的 radix tree 的实现
chi
最简单的框架:
- 核⼼代码 1200 ⾏
- 适合作为 web 框架⼊⻔项⽬
- 在其基础上整合其它组件,⽅便
主要组件:
- Router,⽀持分组
- Middleware/Chai
- Context
Gin
⽼牌框架
- Star 最多
- 核⼼代码 3000 ⾏
- ⽤户很多很多
主要组件:
- Router,⽀持分组
- Middlewar
- binding,将 decoder 和 validator 合⼆为⼀,变成了 binding 组件
- Logger,功能⽐较弱
- Context
echo
⽼牌框架
- 核⼼代码 1900
- 中规中矩
主要组件:
- Router,⽀持分组
- Middlewar
- binding,没有 validato
- Logger,实现在框架外部:https://github.com/labstack/gommon/blob/master/log/log.go
- Context
fiber
2020 年开始做的框架
- 基于 fasthtt
- 参考了 Express.js 的设计
主要组件:
- Router,⽀持分组
- Middleware
- Context
Beego
元⽼框架
- 与 martini,gin,beego 曾经是 Go 圈⼦三个最⽕的框架
- 国⼈的第⼀个 Go 的世界级项⽬
- MVC 框架,适合 PHP 程序员上⼿
主要组件:
- Router,⽀持分组
- Filter(其实就是 middleware
- Contex
- Task(类似 spring 框架中的定时任务
- orm、httpclient、cache、validator、config、swagger、template 等
小结
⼤多数流⾏的 Go 开源 web 框架本身功能并不是很多,最简单的框架,只需三个组件:
- Router
- Middleware
- Context
微服务框架
相⽐ web 框架,微服务框架的组件更多:
- Config:配置管理组件
- Logger:遵守第三⽅⽇志收集规范的⽇志组件
- Metrics:使框架能够与 Prometheus 等监控系统集成的 metrics 组件
- Tracing:遵守 OpenTelemetry 的 tracing 组件
- Registry:服务发现组件
- MQ:可以切换不同队列实现的 mq 组件
- 依赖注⼊:wire,dig 等组件
go-micro
主要组件:
go-zero
YoYoGo
DubboGo
Kratos
如何评判框架优劣
框架设计需要考虑的问题
- 自动化
- 平台化
- 集成化
- 组件化
- 插件化
- 通用化
如何评判框架优劣
自动化
- Layout 代码⾃动⽣成(DDD/Clean Arch
- 服务上线⾃动发布
- ⾃动⽣成接⼝⽂档
- 服务接⼊ SDK ⾃动⽣成
- 常⻅ code snippet(boilerplate) 内置在 CLI ⼯具内
- 不要让⽤户去复制粘贴,我们来帮他⾃动写好
平台化
- IDL 在平台中管理
- 接⼝⽂档可检索
- 服务上线/部署流⽔线化
举例
- step 1,修改服务名,服务级别(p0, p1)
- step 2,选择依赖资源,db,redis,mq,外部服务
- step 3,选择服务部署集群,⾼可⽤要求
- step 4,部署
集成化
- 框架提供所有基础设施 SDK(log, tracing, config center,orm/sql builder,es sdk,clickhourse sdk, mq, etc..
- 开箱即⽤,核⼼依赖⽆需外部站点寻找
- 专⻔的 organization 下维护其它⾮核⼼依赖
- 解决⽤户的选择困难症
组件化
- 稳定性需求,沉淀为统⼀组件
- 公司内历次故障经验都应尽量沉淀为避免/解决问题的组件(可以是重试组件中的规则,也可以是静态扫描⼯具中的⼀个 linter)
- 不要让每个⼈都必须读⼀遍 Google SRE 书才能做好稳定性
插件化
- ⾯向接⼝编程
- 组件以 plugin 形式提供(不是 Go 语⾔的那个 plugin)
通用化
- 主要针对开源框架
- Leave options open by Uncle Bob
- 让⽤户有选择权(我喜欢 etcd/zk 做注册中⼼,我偏要⽤),可以通过插件化来达成
- Go-micro 是⼀个很好的范例
对于企业内部框架来说,通⽤并不是⼀定要追求的⽬标
小结
- 对于企业场景来说,⼤⽽全就是好
- 对于开源场景来说,给⽤户选择权才是好
如何看待社区观点
框架应该做薄
核⼼观点:
- Less is more
- 框架的核⼼只保留通⽤接⼝和简单流程
- 复杂的选择问题交给⽤户
- 我们写 Go,就是因为不喜欢 Java 那样臃肿的框架!
如果框架不愿意帮业务解决依赖的坑,那每个业务都要被相似的问题坑⼀遍。
OLTP 到底该不该使⽤ ORM、sql builder
如果线上出现了慢 SQL,我想要⻢上定位到代码位置呢?
使⽤规范的 SQL <-> struct 绑定⽅式,可以整合静态分析、部署⼯具直接定位到哪⼀次部署引⼊了慢 SQL
但是:⽬前没有看到任何⼀家公司实现了上述诊断链。
框架内容多,升级负担极⼤,要推每个业务⽅去升级
- 确实是这样,但这是框架组的责任
- 基于 service mesh 和 dapr 的架构⼀定程度上解决了这个问题
框架不应该对业务⾃⼰选内部库造成的依赖冲突负责
- 框架是稳定性/⼯程效率交给业务研发的产品
- 产品问题就应该让负责⼈来改进,甩锅怎么能⾏呢
⼀些可以借鉴的思路
- IDL 之间可以使⽤技术⼿段可以互相转换(第⼆节课有提到)
- 要做平台化,可以适当屏蔽 IDL 的语法,可以参考 openapi
- 业务代码⼊⼝不应与任何协议绑定,如图:
References
why library?
Go Micro 初探及其底层架构
Go-Micro 微服务框架设计
Why I Recommend to Avoid Using the go-kit Library