当我们有了一个应用构想的时候,往往需要快速实现一个原型进行验证及试错。在开 始阶段,应用的业务方向调整比较频繁,此时,我们更多是考虑一个应用基本功能的实现, 以及能否快速迭代以跟上业务方向的调整,实现一个应用的快速成长,并且在实践过程中 尽可能做到为后续的架构升级做好铺垫。
在应用的初创阶段,访问量并不大,一个比较基础的单体架构的系统足以支撑起整个 业务。因此,本章我们不涉及服务拆分、服务化这些内容,而是从做出一个完整的系统出 发,主要的任务是完成基本的业务需求,这些需求包括:选择合适的技术栈;能够快速进 行功能的迭代开发,做好基本的高可用;规范整个开发流程;从一开始就要考虑到应用安 全,不犯常见的安全错误;应用部署后,对应用进行基础的监控,更早地发现系统缺陷及 性能问题。因为随着业务的成型,访问量随时可能暴涨,对应用监控的主要目的是保证我 们的产品能够正常地服务用户,及时发现应用故障,以期快速解决故障。
技术选型
一个基本的单体架构,其功能是以实现产品业务为准,一般来说,其功能需求主要包 括业务逻辑如何实现及相关的数据如何存储。业务逻辑的实现一般涉及相关业务技术的选 型,即如何选择合适的框架来支撑业务。关于数据存储,针对不同的数据类型可以选择不 同的存储方式:对于结构化数据,一般选择关系型数据库;对于非结构化数据,一般选择 键值对数据库;如果有大量的图片、视频的存储需求,一般选择专门的对象存储系统进行 存储。
业务框架选型
当我们实现一个应用的时候,最先面对的就是使用什么样的应用框架。一个强大的应用开发框架可以大大节省我们的时间和精力,避免重复造轮子。
选型因素
在做具体的业务框架选型的时候,往往要考虑常见的选型因素,以指导我们做出比较 合理的选型。
业务相关性
业务因素是我们在做框架选型时需要首先考虑的因素。当我们实现一个特定的业务功 能时,某些编程语言中恰好有对应的三方库实现,这个时候选择这门编程语言,往往能达 到事半功倍的效果。当我们选择好一个框架后,也就选择了一门编程语言,因此该编程语 言下的三方库是否足够多,一些常见的功能是不是都能实现也是一个考虑因素。如果我们 的业务更多是数据库的增删查改,那么当框架提供了接口良好的数据库抽象,有比较好的 数据持久化支持时,就会大大提高我们的开发效率。如果我们的业务是一个基于长连接的 实时服务,那么使用纯异步的 Node.js 可能更合适。因此,框架的选型与我们的业务类型息 息相关,也是我们首要考虑的因素。
框架流行度
越流行的框架,使用的人越多。使用的人越多就意味着,当我们在遇到问题的时候, 就会有更多潜在的人会回答我们的问题。一个活跃的社区,可以帮我们解决绝大部分问题, 因为很多问题在我们遇到之前,已经有别人遇到了。当我们在网上搜索相关问题的时候, 也许可以直接定位到答案。
越流行的框架,学习的人就越多。当我们需要招聘新人的时候,也更容易招到对口的 人,减少我们的招聘成本。因此在做框架选型的时候,不要为了图“新奇”,图“品味”, 去选择一些比较小众的框架或者小众的编程语言。
这里还要说明的一点就是,流行度是有时间因素的,前些年比较流行的框架,到了现 在可能已经不再流行了,比如 Struts 2。而当今的一些流行框架,随着时间的推移,也可能 被更新的框架所取代。因此这里的流行度,都是相对在一定时间内的。
学习曲线
每一个框架都有自己的特性,命名规范、文件夹结构和使用方式都不相同。有些框架可以很灵活地配置,但是带来了配置的复杂性;有些框架则使用“约定优先配置”的思想 对配置进行了约定,使得配置非常简单,但是面对复杂业务的时候又表现得力不从心。
这些不同带来了面对不同业务时候的不同学习曲线。陡峭的学习曲线,往往为学习者 带来太多学习的负担。而一个学习简单、配置简单的框架,则可以减少后续团队增加新成 员时的成本,并使运维配置也变得简单。
还有,如果对这个框架所使用的语言不熟悉,同时学习语言加框架会导致学习曲线更 加陡峭,选择一个用熟悉的编程语言写的框架往往学习起来更轻松。因此在选择框架的时 候,尽量选择比较流行的编程语言写的框架。
更进一步地说,框架源码如果有比较好的可读性,当我们需要了解这个框架的实现细 节时,也能比较快速地入门去阅读源码。因此,框架源码可读性的好坏,在一定程度上, 也影响了我们对这个框架具体实现细节的了解,从而影响我们对这个框架的深入应用。因 此,请尽可能选择源码可读性好的框架,使得源码阅读的学习曲线比较平缓。
文档
一个具有良好文档的框架,往往是我们使用这个框架的保证。框架中大量的代码片段、 例子代码和教程都可以帮助我们更好地使用这个框架。而一个文档匮乏的框架,无论吹嘘 得有多好,没有良好的文档,我们将不得不去摸索使用,甚至不得不去阅读其代码。这些 都会减缓开发的效率。不过很幸运的是,很多优秀的框架,也都有着优秀的文档。
社区支持
如果一个框架非常适合你的业务逻辑,但是这个框架已经很久没有更新了,那么在做 框架选型的时候,就需要特别小心。一个长期不更新的框架,或许已经被社区放弃了。使 用该框架后,一旦遇到了问题,我们无法从官方社区获得支持,只能靠我们自己去解决, 可能会拖慢我们的开发进度。
单元测试
在开发过程中,单元测试是必不可少的部分。单元测试能够尽快发现某一部分代码的 bug,提高代码质量,减少项目集成的成本。因此,如果框架提供了对单元测试的支持,用 户可以在框架之上直接写自己的单元测试逻辑,以提高开发效率。
可扩展性
框架是否提供了扩展接口也是我们要考虑的因素。随着业务的发展,框架的基本功能 逐渐不再满足我们的功能及非功能需求。如果其提供了良好的扩展接口,我们就可以基于 这些扩展接口,实现自己的一些定制功能。
许可证
虽然目前绝大部分应用框架都是开源的,但是一些框架可能还需要付费使用,或者一 个框架的某些扩展部分需要付费使用。因此在做框架选型之前有必要去简单了解一下这个 框架的授权协议,以防在使用中出现知识产权的问题。
上面这些选型因素之间不是孤立的,他们是相辅相成的。一个流行的应用框架,一般 都具有良好的文档,良好的社区支持,可扩展性很强,适合绝大部分场景下的业务,学习 入门简单等特点。反之一个学习入门简单,文档齐全的框架又会有更多的人去使用,形成 一个良好的社区文化,使得框架更流行,从而又会反哺框架的发展,形成一个良性循环。
在应用的初始阶段,我们可以不断地通过原型试错,从而选择一个比较适合我们具体 业务的框架,做一个比较好的技术选型。而一旦选定了技术框架,随着我们在框架上面开 发的业务越来越多,后续如果想做框架转换将会越来越困难。因此在最初的框架选型阶段 有必要非常慎重。
另外,当我们为了完成某个特定的业务功能时,可以使用的三方库的选择也有很多。 一个合适的三方库的选择同样需要考虑上面讨论到的因素,文档是不是完整,许可证是不 是友好,用的人是不是很多等。一个好的选择,会带来更少的问题,提高开发效率,使得 我们能够更快地进行迭代。
文章节选自《云原生应用架构实践》 网易云基础服务架构团队 著