无服务器计算

新的一年开始了,我翻回去看了看先前写的文章,我似乎很少谈及技术话题;特别是过去的 2018 年,我记录下的多是生活中的点滴。不知为何,今年我也想偶尔地记录一下自己对一些科技的想法。此外,我还决定在新的一年里做一些个人在 GitHub 上公开的项目。得益于 GitHub 最近允许个人开发者可以在三人以下团队无限创建私有代码仓库,我可以在代码公布之前先做好私下的测试。

过去有大约一年的时间,我都花在了学习无服务器计算 (Serverless) 这一新兴的云计算架构上。无服务器计算又可以被称为功能即服务 (Function as a Service, FaaS) 架构,这一架构相比传统的服务器架构来说,只存在于云计算领域。所谓的“无服务器”,仅仅是因为这一服务背后使用的服务器集群是由云计算服务端提供商进行维护;作为云计算服务的使用者,不需要过多操心诸如服务器维护之类的可能造成下线或者服务降级的问题。

传统架构

传统的服务器架构一直都是行业的主流,即使是在无服务器计算开始流行的今天,它们也是搭建在传统架构之上。传统的服务器架构可以搭建在业者自有的服务器平台上,也可以选择云计算服务提供商。从大约 2004 年开始,云计算逐渐起步,经历十多年的发展,现在有很多组织都将他们的服务器转移到了云计算平台上。最早期的服务器架构,需要业者自行搭建机房,一切几乎是从零开始:购买域名、IP 地址、交换机、服务器硬件、线缆等。系统工程师还需要预判流量的增长情况,适当更新硬件、购买更多设备。除此之外,服务器还会因为操作系统更新出现之前提到的维护时间窗口等问题。特别是对于中小规模的业者,这种架构也无法很好地解决突然增长的流量,服务器维护的费用也可能对于他们是一笔不小的指出。

后来,这一架构被移植到了云计算平台上。云计算的用户们不再需要自行搭建机房,也不需要购买硬件了。他们可以轻易地把他们在本地机房运行的服务器程序转移到在云上的服务器里。因为不需要购买硬件,这让业者可以更好地应对突增的流量。例如,利用平衡负载器等的服务,业者可以将流量平均发往每一台服务器,甚至可以在几分钟之内扩大自己的服务器集群用来处理快速增长的流量。因为不需要购买服务器,节约下了购买、更新硬件和租用场地用作机房的开支。然而,服务器仍然会出现一定的维护时间窗口——尽管这一维护一般由云服务提供商提前一个月或者更早计划,让用户有充足的时间处理服务器下线的应对方案。此外,无时无刻都在运行的服务器也是一笔开支——特别是使用计算能力非常强的服务器时。

无服务器

考虑到上述问题,最近几年出现了无服务器计算架构。简单地说,无服务器计算架构将原先一个传统服务器中提供的服务碎片化为一个个微服务 (Microservices)。当最终用户需要使用某一个服务的时候,仅仅在云端触发相对应的程序,待执行完成之后便清理使用过的资源。这一过程往往只有几百毫秒到几分钟,所谓被触发的程序,往往也非常精炼。这一架构让静态的网页界面可以与动态内容相结合而不用依赖第三方提供的服务。

举一个更加具体的例子:假如我有一个可以登录发表评论的网站,如果不利用无服务器计算架构,即使网站内容可以通过一些程序生成静态的 HTML 页面,登录以及评论功能也需要服务器后端以及数据库完成。如果网站的管理者不希望使用传统的服务器架构来达成这一需求,就只能利用一些提供评论管理的第三方软件。由此产生的第一个问题就是这些软件可能无法很好地和原网站的设计很好地兼容;更重要的是,可能没有 API (Application Programming Interface, “应用程序接口”) 提供开发移动客户端的能力。然而,通过无服务器计算架构,这一点可以被轻松实现。首先,我们可以使用云计算服务提供商提供的身份提供商 (Identity Provider, IdP) 服务来实现用户注册、登录。在静态的 HTML 页面中,我们可以提供身份提供商预先设计好的登录页面,也可以自定义登录界面,并与身份提供商的 HTTP API 相连接。如果一个用户成功登录,身份提供商会将一组 JWT 令牌 (JSON Web Token) 返回到最终用户的浏览器中。存在于静态 HTML 页面之后,在浏览器内运行的 JavaScript 脚本可以获取令牌并且验证身份,并且 jQuery 将用户的个人资料更新到 HTML 静态界面中。假设用户此时点击了一篇文章的链接,在加载页面的 URL 的同时,浏览器的后台会将用户之前获取到的令牌、文章的 ID 等信息一同发送到一个 HTTP API 节点,这时 HTTP API 节点将会验证身份是否有权限访问这一文章。如果有,将会开始运行一段代码,获取文章内容以及评论,并且将获得到的所有信息全部发送回浏览器。与之前类似,在浏览器中运行的 jQuery 代码将获取到的内容渲染到页面之中。这一整个流程一般来说发生在几百毫秒到几秒之内,在将内容发回浏览器之后,先前占用的硬件资源也会被全部释放。

这就是无服务器计算的最大特点:服务只在需要的时候才会运行。这大大降低了中小规模组织及个人在开发基于云计算的产品时的预算。同时,因为无服务器计算架构多基于 HTTP API 而设计,将产品从网页端移植至移动客户端也不存在很多障碍。此外,这一架构不存在系统维护时间窗口,云计算服务提供商也会为用户管理突增流量以及异地容灾。这不仅仅是对用户节约开支,云服务提供商的冗余硬件资源也可以通过这一架构更好地利用。

然而,这一架构也并非没有缺点。首当其冲的是这一架构仅能通过云计算服务提供商实现,而不同云计算服务提供商之间的差异也会导致互相移植的难度。因此,经过一段时间的运营以及开发,可能会产生对某一云计算平台很强的依赖性。此外,对延迟非常敏感以及需要长时间运行的服务器程序可能会更加倾向于使用传统的服务器架构,例如网络游戏的服务器。