FaaS 连接并访问传统数据库会增加额外的开销,我们可以采用数据编排的思想,将数据库操作转为 RESTful API。顺着这个思路,我引出了后端应用的 BaaS 化,一句话总结,后端应用 BaaS 化就是将后端应用转换成 NoOps 的数据接口。那怎么理解这句话呢?
前面的“待办任务”Web 应用,这个项目前端是单页应用,中间用了 FaaS 做 SFF 数据网关,后端数据接口还要 BaaS 化。这个案例会贯穿对于Servless的探索,所以你一定要动手 run 一下。
这个架构的优势是什么呢?我们将这个图变个形,你就更容易理解了。
从左往右看上面这张图。用户从浏览器打开我们网站时,前端应用响应返回 index.html;然后浏览器去 CDN 下载我们的静态资源,完成页面静态资源的加载;与此同时,浏览器也向前端应用发起数据请求;前端应用经过安全签名后,再将数据请求发送给 SFF;SFF 再根据数据请求,调用后端接口或服务,最终将结果编排后返回。
从图里你可以看到,除了数据库是 Stateful 的,其它节点都已经变成了 Stateless。如果你公司业务量不大的话,这个架构其实已经足够了。就像传统的 MVC 架构一样,单点数据库,承载基本的并发量不是问题,而且数据也可以通过主从结构和客户端读写分离的方式来优化。
但 MVC 架构最大的问题就是累积,当一个 MVC 架构的应用,在经历长期迭代和运营后,数据库一定会变得臃肿,极大降低数据库的读写性能。而且在高并发达到一定量级,Stateful 的数据库还是会成为瓶颈。那我们可以将自己的数据库也变成 BaaS 吗?
要解决数据库的问题,也可以选择我上节课和你说的云服务商提供的 BaaS 服务,比如 DynamoDB。但云服务商 BaaS 服务究竟是怎么做到的?如果 BaaS 服务能力不全,不够满足我们的需要时怎么办?看看传统的 MVC 应用中的数据库怎么改造成 BaaS。
当然,BaaS 化的过程有些复杂,这也正是我们后面需要慢慢探索;后端应用 BaaS 化,就是 NoOps 的微服务。在我看来后端应用 BaaS 化,跟微服务高度重合,微服务几乎涵盖了我们 BaaS 化要做的所有内容。
微服务的概念
微服务的概念对很多做后端同学来说并不陌生,尤其是做 Java 的同学,因为早些年 Java 就提出 SOA 面向服务架构。微服务算是 SOA 的一个子集,2014 年由 ThoughtWorks 的 Martin Fowler 提出。微服务设计之初是为了拆解巨石应用,巨石应用就是指那些生命周期较长的,累计了大量业务高度耦合和冗余代码的企业应用。
Serverless 专栏并不打算给你详细地讲解微服务,但是希望你能一定程度上了解微服务。FaaS 和微服务架构的诞生几乎是在同一时期,它俩的很多理念都是来自 12 要素(Twelve-Factor App),所以微服务概念和 FaaS 概念高度相似,也有不少公司用 FaaS 实现微服务架构;不同的是,微服务的领军公司 ThoughtWorks 和 NetFlix 到处宣扬他们的微服务架构带来的好处,而且他们提出了一整套方法论,包括微服务架构如何设计,如何拆解微服务,尤其是数据库如何设计等等
我们后端应用 BaaS 化,首先要将复杂的业务逻辑拆开,拆成职责单一的微服务。因为职责单一,所以服务端运维的成本会更低。而且拆分就像治理洪水时的分流一样,它能减轻每个微服务上承受的压力。
这里简单说微服务主要就是想引入微服务拆解业务的分流思想和微服务对数据库的解耦方式。
微服务 10 要素
谈起微服务,很多人都要说 12 要素,认为微服务也应该满足 12 要素。12 要素当初是为了 SaaS 设计的,用来提升 Web 应用的适用性和可移植性。我在做微服务初期也学习过 12 要素,但我发现这个只能提供理论认识。
其实可以归纳经验总结为微服务的 10 要素:API、服务调用、服务发现;日志、链路追踪;容灾性、监控、扩缩容;发布管道;鉴权。
- 无需用户关心服务端的事情(容错、容灾、安全验证、自动扩缩容、日志调试等等)。
- 按使用量(调用次数、时长等)付费,低费用和高性能并行,大多数场景下节省开支。
- 快速迭代 & 试错能力(多版本控制,灰度,CI&CD 等等)
你可能发现跟微服务的要素有大量的重合。API 就是 RESTful 的 HTTP 数据接口;服务调用你可以理解为就是 HTTP 请求;服务发现你可以理解为我们只能用域名调用我们的 HTTP 请求,不能用 IP;日志、容灾、监控都不难理解;链路追踪,是微服务重要的一环,因为相对传统 MVC 架构,我们一个请求在后端的调用链增长了,为了快速定位问题,我们都需要打印整个调用链路的异常栈;发布管道和鉴权,和我们的 FaaS 也有很重要的关联。
通过前面的案例下面主要看看微服务如何让数据库解耦。
我们先分析一下“待办任务”Web 服务。上一讲末尾我的作业其实已经为你准备好了,我们一起看看 index.js 文件,这是一个典型的 MVC 架构的应用。View 层就是 index.html 和静态资源文件;Model 层,我们引入 lowdb 用一个 db.json 文件代替数据库;Control 层,就是 app.METHOD,处理 /api/* 的数据逻辑。微服务是解决后端应用的,所以我们只需要关注 Control 层。
API 的数据处理,主要有两个,一个是 /api/rule 处理待办任务的,一个是 /api/user 负责用户登录态,而且我们“待办任务”主要的数据模型也就是待办任务和用户这两个。那我们可以将后端拆分出两个微服务:待办任务微服务和用户微服务。这里我要强调下,我只是为了向你演示微服务才这样做,在实际业务中,这么简单的功能,没必要过早地拆分。
初步拆解,我们将 index.js 中的数据库移走了,而且拆分后各微服务的数据库比原来混杂在一起简单且容易维护多了。user.js 负责用户相关业务逻辑,只维护用户信息的数据库,并且暴露 RESTful 的 HTTP 方法;rule.js 负责待办任务的增删改查,只维护待办任务的数据库,并且暴露 RESTful 的 HTTP 方法;index.js 只需要负责将请求 HTTP 返回给数据编排。
HTTP 协议要满足我们的服务调用与发现,发布的 user.js 和 rule.js 必须使用域名,例如 api.jike-serverless.online/user 和 api.jike-serverless.online/rule。这样新扩容的机器 IP,只需要注册到这个域名下就可以被服务发现 IP 并调用了。
总结
我们为了避免在 FaaS 中直接操作数据库,而将数据库操作变成 BaaS 服务。为了理解 BaaS 化具体的工作,我们引入了微服务的概念。微服务先将业务拆解成单一职责和功能的小模块便于独立运维,再将小模块组装成复杂的大型应用程序。这一点上跟我们要做的后端应用 BaaS 化相似度非常高。所以参考微服务,我们先将 MVC 架构的后端解成了两个微服务,再用微服务解耦数据库的操作,先将数据库拆解成职责单一的小数据库,再用消息队列同步数据库和副本,从而将数据变成了 Stateless。
现在我们再来回顾一下这节课的重要知识点。
微服务的概念:它就是将一个复杂的大型应用拆解成职责单一的小功能模块,各模块之间数据模型相互独立,模块采用 API 接口暴露自己对外提供的服务,然后再通过这些 API 接口组合成大型应用。这个小功能模块,就是微服务。
微服务 10 要素:API、服务调用、服务发现;日志、链路追踪;容灾性、监控、扩缩容;发布管道;鉴权。这跟我们要做的 BaaS 化高度重合,我们可以借助微服务来实现我们的 BaaS 化。
解耦数据库:通过额外进程让数据库与副本直接通过消息队列进行同步,所以对于微服务应用来说,只需要关注自身独享的数据库就可以了。微服务通过数据库解耦,将后端应用变成 Stateless 的了,但对后端应用本身而言,数据库还是 Stateful 的。
基础篇:FaaS的拆解和编排
- 阿里举集团之力趟坑Serverless,到底它能解决什么问题?