从电子邮件系统看微服务的建设
以前总有人问我微服务相关的问题,但微服务绝不是一篇文章能说清楚的事,所以我和Gary小王子商量了一下,在极客时间上 开发 了一个全新的白板课程,第一个产品就是微服务,以短视频讲系统内容。结果还是有人问,比如微服务到底有多「微」,什么类型什么规模的系统适合微服务…等等。
今天我就用电子邮件这个人民群众喜闻乐见的工具系统做一个类比。
随着微服务的实践和火热,关于「微」的概念出现了很多不同层面的理解。 一个开发者普遍认可的定义是:一个微服务应该小到只做一件事。但是深入追究,你会觉得这并不是一个有意义的解释——「一件事」这个概念本身就有可大可小,规模类型各不相同,它并不能起到有效约束微服务大小的作用。 事实上,我同样反对那些认为每个独立的服务应该能且仅能实现单一功能的观点。比如,有个函数是根据三个输入参数来计算输出——你真的认为我们有必要将这个方法单独抽离成一个微服务并独立部署么?
你要真这么做了,估计二爷都不能答应。
类比是跨越鸿沟最好的桥梁,来,我们举一个例子:比如电子 邮件系统 。为了尽量简单化这个模型,我们假设它是纯粹的电子邮件系统,只有基本功能(如登录、退出、用户设置、写邮件、发送邮件、删除邮件、查看收件箱、创建/修改文件夹、记录通讯录、搜索邮件等)。从单一模式的设计角度出发,我们可以用一个应用来实现所有功能。我们也可以用模块化设计的方式将它的功能拆分成模块,比如用DDD(领域驱动设计)的方式来拆分。当然,我们需要一些其他的依赖来实现某些功能——UI、数据存储、外部搜索系统等。最后,我们可能得到一个六边形或多层结构的单体应用。
所有与这个邮件系统相关的团队都必须紧密联系在一起,一旦应用有任何改变,(几乎)所有人的代码都会受到影响。事实上这个邮件系统就是一个大的Package,把系统功能、代码和工程师都装进去了,这种应用被我们成为All-or-Nothing,要么生存,要么死亡,我们只能选择运行/不运行整个系统,没法灵活的开启/关闭某些功能。对于某些规模的团队和系统,这样的结构也可能很好,事实上很多创业公司都是这么过来的,机会很少有创业公司在一穷二白的时候设计微服务架构。
随着团队和系统规模的增长,产品的演进,很多团队开始不满足于这种架构,大家希望将整个应用切分成相对独立的、有着自己生命周期的子应用/服务/库,那么就要进行系统的切分。
如何切分?首先,登录/登出(或者叫授权系统)和用户资料这两块可以拆分成单独的服务。并且,基于安全性的考量,它们应该被单独设计和实现。邮件和文件夹两者联系很紧密,所以我们可以将它们划分到一个服务(你也可以尝试拆分它们,尽管我个人并不建议)。接下来,如果我们有不同的通讯协议,如web interface、POP3、IMAP、SMAP,可以将每个协议的实现部分拆成对应的服务。同样,信息存储,可以被抽离成独立的服务。通讯录加上它的UI与它的API可以被抽离成一个独立的服务。
最后,我们可能将整个邮件系统拆离成15~20个独立服务。对于任意的请求/操作,我们都可以将它映射到若干微服务之上——比如,用户在表格里输入数据之后,点击了一个按钮,数据应该被保存在这个表格对应的数据库里。我们会用三到五个服务组合来处理整个逻辑。
总结一下,将「服务拆分到尽可能小」并不是我们的目的。如果你这样做了,只能说明你将拆分服务当作了你的首要业务,而忽视了业务的交互性和为什么要拆分。按照业务逻辑与迭代频率区分,选择更适合自己的模块方式,才是微服务的最佳实践。
(本文部分内容选自我邦「聊聊架构」,作者Andy Zhang,池建强修改润色并增删部分内容)。