理想框架到底是什么样子的?这个终极问题,闭门造车是无法得到答案的,所以今天,我想让你先从埋头搭建 Web 框架的视角中暂时跳出来,站在更高的角度来纵观全局。
开源框架怎么比较
有如下几个参数:
标准 | 说明 |
---|---|
核心模块 | 服务启动方式,路由分发机制 上下文ctx封装性、中间件机制的设计 |
功能完备性 | 是否提供日志模块、命令行工具、缓存机制等 |
框架扩展性 | 扩展某个功能时,改动是否较大,是否支持功能实现的可插拔 |
框架性能 | 每秒支持多少请求,是否有性能问题 |
文档完备度/社区活跃度 | 是否有完善文档支持,社区是否足够活跃 |
核心模块
核心模块就是之前讲的:HTTP 服务的启动方式、路由、Context、中间件、重启方式,它们的实现非常关键,往往影响到整个框架的表现,也能直接体现出框架作者的开发水平。
框架的核心模块就好像是汽车的引擎,一旦核心模块出了问题,或者有隐性的缺陷,后果往往是无法弥补的。理想的核心模块必须要有设计感,有自己的思想,代码质量、性能都不能出问题。
功能完备性
框架最好能尽可能多地提供功能或者规范,比如有自己的日志模块、脚手架、命令行工具,甚至自己的 ORM、缓存等等。
要知道,框架的本质还是在于提高开发效率,在团队中,我们希望不同水平的同学能写出基本一样的代码,那就要靠框架这个顶层设计来规范了。试想一下,如果框架中提供了很方便的参数验证规范,那在开发应用的时候,还有谁愿意走解析和正则匹配来验证参数呢?
在功能完备性的选择上,我们往往会根据之后是否希望自定义需求来确定。这里说的自定义需求,指的是定制自己的日志、ORM 等模块的需求。
框架扩展性
理想的框架,它的扩展性一定要好。框架要做的事情应该是定义模块与模块之间的交互标准,而不应该直接定义模块的具体实现方式。我可以在这个标准上扩展出我需要的功能,这样整个框架才会比较灵活。
Web 领域的技术边界在不断扩展,谁也无法保证框架中所用的库,哪怕是最基本的日志库,能永远满足需求。当框架使用者想为应用增加一个功能,或者替换某个第三方库的时候,如果改动的地方非常多,要大动干戈,甚至根本就无法支持替换和增加,那这个框架的扩展性就比较弱了。
框架性能
虽然大部分框架都是封装 net/http,但是封装程度不同以及具体的实现选择不同(使用的路由匹配、上下文机制等),就会有不同的性能表现。
我们选择框架之后,最终是要在框架上运行代码的,如果运行效率有指数级别的差距,是不能接受的。
其实对框架性能来说,大部分场景里,我们是不会有极致性能需求的。所以看各种框架的性能评估,我们不应该把各个框架孤立出来看,应该将差不多量级的性能归为一组。不要去比较单个框架的性能差异,而应该去比较不同量级组之间的性能差异,因为在相同量级下,其实框架和框架之间的性能差别并不是很大。
文档完备度及社区活跃度
开源不仅仅是将代码分享出去,同时分享的还有使用文档,官方必须提供足够的介绍资料,包括文档、视频、demo 等。
文档和社区是需要不断运营的,因为在使用的过程中,我们一定会遇到各种各样的问题,官方的回复以及一个活跃的社区是保障问题能得到解决的必要条件。
所以当我们选择一个框架的时候,官网、GitHub 的 star、issue 都是很好的衡量标准。当选择框架之后,不妨每天花一点时间在这个项目的官网、GitHub 或者邮件组上,你会得到很多真实信息。
比较开源框架
Beego
- 启动方式:多种,支持HTTP/HTTPS、CGI、Graceful
- 路由原理:字典树,特色的自动匹配路由和注解路由
- Ctx设计:隐藏在controller 结构中,不作为函数第一个参数
- 功能完备性:提供了很多周边的功能。比如 Beego 提供了一个原生的 ORM 框架、自定义的 Logger 库、参数验证 Validate 库,甚至还默认提供了管理 GC、Goroutine 等管理接口。
总体来说,使用 Beego 的最大感受就是“全”。这是一个很全的框架,开发 Web 应用所需要的所有组件基本都能在这里找到,如果选择它做业务开发,功能完备性是最重要的因素。所以在从零开始,希望快速开发的场景中,我们会尽量选择使用这个框架。
Echo
- 路由:字典树,但不是为每个http方法建立一个树,而是只整体建立一个树。这样每个叶子节点都存放了不同了http方法的handler。
Echo 的使用者更看中扩展性和框架性能。和定位一样,它是一种高性能、可扩展、轻量级的 Web 框架,但麻雀虽小,五脏俱全。目前看起来,它的社区活跃度比 Gin 框架稍差一些(从两者的中间件贡献数可以看出)。所以我感觉,Echo 框架更适合个人开发者,而且需要有一定的扩展框架能力。
Gin
- 路由: 字典树,但节点不是按斜杠分隔的请求路由,而是相同的字符串部分,这样使用索引来加速子树的查询效率。这部分路由是使用的第三方的 httprouter 包。
- Ctx设计:实现了标准库的Context接口
- 中间件:定义了Middleware函数,可自己具体实现
总体来说,Gin 比较适合企业级团队使用。它的社区活跃度较高,社区贡献的功能模块较多,能很好补充其功能完备性;同时 Gin 的扩展性也很好,我们可以在社区贡献模块和自研模块中做出很好的取舍。
理想的框架是什么样的
其实从刚才的分析也可以看出来,这个问题是见仁见智的,和你的工作经验、技术阅历、甚至技术的理念都有关系。有的人追求的是世界上运行速度最快的框架;有的人追求的是灵活性最高的框架;有的人追求的是功能最全的框架。
具体你要根据自己的应用场景来选择,包括你 Web 应用的业务场景、并发需求、团队规模、工期等等。回看刚才提出的五个选择维度,以我们聊过的三个 Web 框架为例。
在保证框架的核心模块能满足要求的情况下,我们一般在功能完备性和框架扩展性之间取舍。
如果你开发一个运营管理后台,并发量基本在 100 以下,单机使用,开发的团队规模可能就 1~2 个人,那你最应该考虑功能完备性,明显使用 Beego 的收益会远远大于使用 Gin 和 Echo。因为如果你选择 Gin 和 Echo 之后,还会遇到比如应该选用哪种 ORM、应该选用哪种缓存等一系列问题,而这些在功能组件相当全面的 Beego 中早就被定义好了。
如果你有一定的团队规模,有比较高的并发量,而且你感觉后续对框架的改动需求或者扩展需求会很高,比如你希望自己开发一个适合团队使用的缓存方法。那么这个时候,你应该把框架扩展性放在最高级,可能 Gin 和 Echo 更适合你。如果你要更多的灵活性,你可能会考虑直接从 net/http 标准库开始,不使用任何的开源 Web 框架。
所以,选择框架信奉一个原则:只选最适合的,不选最贵的。如果你在几个框架中犹豫不定,除了可以用五个维度比较框架之外,你更应该多花时间内省思考清楚你的真正需求。
【小结】:
- 大而全:Beego,封装很多,不用自己再开发。
- 便于扩展和改动:Gin、Echo。