喧哗的背后:Serverless 的概念及挑战


作者 | 许晓斌 阿里云高级技术专家,目前负责阿里集团 Serverless 研发运维平台建设,《Maven 实战》作者,曾经是 Maven 中央仓库的维护者。
导读:本文作者作为阿里集团 Serverless 研发运维平台负责人,从应用架构的角度去分析 Serverless 为何会让那么多人着迷,它的核心概念究竟是什么,并总结了一些落地 Serverless 必然会面临的问题。我曾在
《Serverless 的喧哗与骚动》一文中对 Serverless 今天在行业中所处的状态做了一个比喻,这个比喻是这么说的:Serverless is like teenage sex: Everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it.虽然距离写那篇文章已经过去了半年的时间,但是这种状态在我看来其实没有发生太大的变化,有很多的一线研发或者管理者对 Serverless 技术的理解是非常片面的,有些甚至是错误的。如果缺乏对应用架构演进的理解,缺乏对于云基础设施能力的理解,缺乏对风险的判断,盲目的上新技术可能不仅无法兑现业务价值,浪费精力,然而会引入无谓的技术风险。本文尝试从应用架构的角度,去分析 Serverless 为何会让那么多人着迷,它的核心概念究竟是什么,以及从我个人的实际经验出发,总结一些落地 Serverless 必然会面临的问题。为了能更好的理解 Serverless,让我们先来回顾一下应用架构的演进方式。十多年前主流的应用架构都是单体应用,部署形式就是一台服务器加一个数据库,在这种架构下,运维人员会小心翼翼地维护这台服务器,以保证服务的可用性。随着业务的增长,这种最简单的架构很快会面临两个问题。首先,这里只有一台服务器,如果这台服务器出现故障,例如硬件损坏,那么整个服务就会不可用;其次,业务量变大之后,一台服务器的资源很快会无法承载所有流量。解决这两个问题的最直接方法就是在流量入口加一个负载均衡器,同时单体应用同时部署到多台服务器上,这样服务器的单点问题就解决了,同时这个单体应用也具备了水平伸缩的能力。业务进一步增长,更多的研发人员加入到团队,一起在单体应用上开发特性。这个时候由于单体应用内的代码没有明确的物理边界,大家很快就会遇到各种冲突,需要人工的协调,以及大量的 conflict merge 操作,研发效率直线下降。这个时候大家就开始把单体应用拆分成一个个可以独立开发、独立测试、独立部署的微服务应用,服务和服务之间通过 API 通讯,如 HTTP,GRPC 或者 DUBBO。基于领域驱动设计中 Bounded Context 拆分的微服务架构能够大幅提升中大型团队的研发效率,如果想了解关于 Bounded Context 的更多内容,推荐大家阅读领域驱动设计相关的书籍。应用从单体架构演进到微服务架构,从物理的角度看,分布式就成了默认选项了,这个时候应用架构师就不得不面对分布式带来的新挑战。在这个过程中大家都会开始使用一些分布式服务和框架,例如缓存服务 Redis,配置服务 ACM,状态协调服务 ZooKeeper,消息服务 Kafka,还有通讯框架如 GRPC 或者 DUBBO,以及分布式追踪系统等等,这里就不逐一罗列了。除了分布式环境带来的挑战之外,微服务架构给运维带来的新的挑战。研发人员原来只需要运维一个应用,现在可能就需要十个甚至更多的应用的,这意味着安全 patch 升级,容量评估,故障诊断等事务工作量成倍的增长,这个时候,应用分发的标准,生命周期的标准,观测的标准,自动化弹性等能力的重要性就凸显出来。现在让我们谈下“云原生”这个词,简单的理解,一个架构是否是云原生,就是看这个架构是否是长在云上的。这个“长在”云上的理解不是简单的说用云的 IaaS 层服务,比如简单的 ECS,OSS 这些基本的计算存储;而是应该理解成有没有使用云上的分布式服务,比如 Redis,Kafka 等等,这些服务才是直接会直接影响到业务架构的。前面我们说到,微服务架构下,分布式服务是必要的,原来大家都是自己研发这样的服务,或者基于开源版本自己运维这样的服务,而到了云原生的时代,业务就直接使用云服务了。另外两个不得不提的技术就是 Docker 和 Kubenetes,其中前者标准化了应用分发的标准,不论是 Spring Boot 写的应用,还是 NodeJS 写的应用,都以镜像的方式分发;而后者在前者的技术上又定义了应用生命周期的标准,一个应用从启动到上线,到健康检查,下线,有了统一的标准。有了应用分发的标准和生命周期的标准,云就能提供标准化的应用托管服务。包括应用的版本管理,发布,上线后的观测,自愈等等。例如对于无状态的应用来说,一个底层物理节点的故障根本就不会影响到研发,因为应用托管服务基于标准化应用生命周期可以自动完成腾挪工作,在故障物理节点上将应用的容器下线,在新的物理节点上启动同等数量的应用容器。我们看到,云原生进一步的释放了价值红利。在此基础上,由于应用托管服务能够感知到应用运行期的数据,例如业务流量的并发,cpu load,内存占用等等,业务就可以配置基于这些指标的伸缩规则,由平台执行这些规则,根据业务流量的实际情况增加或者减少容器数量,这就是最基本的 auto scaling,自动伸缩。这就能够帮助用户避免在业务低峰期限制资源,节省成本,提升运维效率。在架构的演进过程中,研发运维人员在逐渐的把关注点从机器上移走,希望更多地由平台系统管理机器,而不是由人去管理,这就是一个很朴素的 Serverless 理解。其实我们都知道,虽然说是 Serverless,但 Server(服务器)是不可能真正消失的,Serverless 里这个 less 更确切的说是开发不用关心的意思。这就好比现代编程语言 Java 和 Python,开发就不用手工分配和释放内存了,但内存还在哪里,只不过交给垃圾收集器管理了。称一个能帮助你管理服务器的平台为 Serverless 平台,就好比称呼 Java 和 Python 为 Memoryless 语言一样。如果我们把目光放到今天云的时代,那么就不能狭义地把 Serverless 仅仅理解成为不用关心服务器。云上的资源除了服务器所包含的基础计算、网络、存储资源之外,还包括各种类别的更上层的资源,例如数据库、缓存、消息等等。2019年2月,UC 伯克利大学发表了一篇标题为
《Cloud Programming Simplified: A Berkeley View on Serverless Computing》的论文,论文中也有一个非常清晰形象的比喻,文中这样描述:在云的上下文中,Serverful 的计算就像使用低级的汇编语言编程,而 Serverless 的计算就像使用 Python 这样的高级语言进行编程。例如如 c = a + b 这样简单的表达式,如果用汇编描述,就必须先选择几个寄存器,把值加载到寄存器,进行数学计算,再存储结果。这就好比今天在云环境下 Serverful 的计算,开发首先需要开发云主机域名分配或找到可用的资源,然后加载代码和数据,再执行计算,将计算的结果存储起来,最后还需要管理资源的释放。论文中所谓的 Serverful 计算,是我们今天主流的使用云的方式,但不应该是未来我们使用云的方式。我认为 Serverless 的愿景应该是 Write locally, compile to the cloud,即代码只关心业务逻辑,由工具和云去管理资源。现在我们对 Serverless 有了一个比较总体但抽象的概念,下面我再具体介绍一下 Serverless 平台的主要特点。管理一两台服务器可能不是什么麻烦的事情,管理数千甚至数万台服务器就没那么简单了。任何一台服务器都可能出现故障,如果自动识别故障,摘除有问题的实例,这是 Serverless 平台必须具备的能力;此外,操作系统的安全补丁升级,需要做到不影响业务,自动完成;日志和监控系统需要默认打通;系统的安全策略需要自动配置好以避免风险;当资源不够的时候,需要能够自动分配资源并安装相关的代码和配置,等等。今天的互联网应用都被设计成能够按可伸缩的架构,当业务有比较明显的高峰和低谷的时候,或者业务有临时的容量需求的时候(比如营销活动),Serverless 平台都能够及时且稳定的实现自动弹性。为了实现这个能力,平台需要有非常强大的资源调度能力,以及对应用各项指标(如 load,并发)非常敏锐的感知能力。Serverful 的方式使用云资源,是按占用而非使用计费的,用户在云上购买了三台 ECS,那么不管用户实际使用了这三台 ECS 多少的 CPU 和内存,他都需要支付这三台 ECS 整体的费用。Serverless 模式下,用户是按实际使用的资源付费的,例如一个请求实际使用了一台 1core2g 规格资源 100ms 的时间,那么用户就只需要为该规格的单价乘以时间(即100ms)付费。类似的,用户如果用的是 Serverless 数据库,那么就只需要为 query 实际消耗的资源,以及数据存储的资源付费。基于 Serverless 架构的代码通常会重度使用后端的服务,将数据、状态管理等内容从代码中分离出去;此外,更彻底的 FaaS 架构则把代码的 Runtime 也交给了平台管理。这就意味着,同样的应用,Serverless 模式下的代码相比 Serverful 模式会少很多,因此不论是从分发还是启动,都会更快。Serverless 平台也通常提供非常成熟的代码构建发布,版本切换等特性,提升交付速度。讲了那么多 Serverless 的好处,但是实际要在主流的场景大规模的落地 Serverless,并不是一件容易的事情,面临的挑战有很多,下面我具体分析一下这些挑战:要实现彻底的自动弹性,按实际使用资源付费,就意味着平台需要能够在秒级甚至毫秒级别扩容出业务实例。这对基础设施是一个挑战,对业务,尤其是比较庞大的业务应用来说,更提出了很高的要求。如果一个应用的分发和启动需要十分钟,那么自动弹性的响应能力就基本无法跟上业务流量的变化了。解决这个问题有很多方法,微服务化能够把巨型应用拆小;而 FaaS 就通过一种全新的应用架构,把应用拆分成更细粒度的函数来做到轻量化,当然,这种方法的缺点是需要业务做比较大的改造。对于 Java 语言来说,Java 9 引入的 modules,以及 GraalVM 的 native image 技术都能够帮助 Java 应用程序瘦身,降低启动时间。一旦 Serverless 的应用或者函数的实例能够实现秒级,甚至毫秒级扩容,相关基础设施就很快会面临巨大的压力。最常见的基础设施就是服务发现和日志监控系统,原本整个集群实例的变化频率可能是每小时几次,现在这个频率变成了每秒几次;此外,如果这些系统的响应能力跟不上实例变化的速度,例如对于业务来说,容器实例 2 秒就完成了扩容,但还需要等待 10 秒服务发现才能完成同步,那么整个体验也就大打折扣了。Serverless 平台依赖标准化的应用生命周期,才能实现完全自动的容器腾挪,应用自愈等特性。而在基于标准容器及 Kubenetes 的体系下,平台能控制的生命周期就是容器的生命周期。因此就需要业务做到业务进程的生命周期和容器的生命周期保持一致,具体包括启动、停止、以及 readiness probe 和 liveness probe 的规范等等。在实际情况中,很多业务虽然做了容器化改造,但实际上容器中除了包含业务主进程之外,还包括很多辅助进程,这也会导致业务进程和容器的生命周期不一致。在 Serverful 的模式下,如果生产环境出现任何问题,服务器是不会消失的,用户会很自然的想到登陆到服务器上去,操作 linux 命令,搜索日志,分析进程,甚至 dump 内存来进行问题分析。到了 Serverless 模式下,我们说用户不需要关心服务器了,也就是说默认情况下是看不到服务器了,那么这个时候如果系统出现异常了,而且平台无法完成自愈怎么办呢?用户还是需要有丰富的排查诊断工具,能够观测到包括流量、系统指标、依赖服务等等各方面综合的状态,以实现快速准确的问题诊断。当围绕 Serverless 模式的全面可观测能力不足的时候,用户必然不会对此感到放心。几乎所有的研发,在职业生涯中第一次部署自己的应用程序的时候,都是面向一台服务器的,或者说是面向一个 IP 的,这是一种非常强大的习惯。今天我们依然能看到很多的应用程序还是有状态的,无法做到自动更换实例;也能看到很多的变更部署行为和 IP 绑定了起来,例如单独选一台特定的机器做 Beta 等等;还有许多发布系统,在做 Rolling Update 的时候,是不会更换实例的,相关的运维系统也就基于这个假设建设能力了。在 Serverless 逐渐落地的过程中,研发需要转换一些思维的模式,逐步地去适应 “IP 随时可能会发生变化” 这样一种心智,转而更多的从服务版本,以及从流量的视角去运维自己的系统。让我们回到《Cloud Programming Simplified: A Berkeley View on Serverless Computing》论文中那个精彩的比喻:今天我们使用云就像是用汇编写代码。我认为这种现状会不断地得以改观,理想情况下,用户交付给平台部署的包中,应该 100% 是用户描述业务的代码。虽然现状远不是那样,不过可以看到很多技术,如 Service Mesh,Dapr.io,cloudsteate.io,都在把与业务无关的,但是分布式架构又必须的逻辑,从业务的运行时中剥离出去,交给平台管理。这种趋势在最近一年中逐渐清晰和强烈,对此 Bilgin Ibryam 在
《Multi-Runtime Microservices Architecture》一文中做了很好的总结,一并推荐阅读。本文中我们看到 Serverless 的演进对应用架构,到持续交付,服务治理、运维监控都提出了新的要求,其实除此之外,Serverless 也会对计算存储网络等更底层的技术设施提出更高的响应能力要求。因此,这其实是一次贯穿应用、平台、基础设施多个层面的,比较彻底的技术演进,有幸参与其中,我觉得还是非常兴奋的。为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。点击即可免费观看课程:
https://developer.aliyun.com/learning/roadmap/serverless“
阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

相关推荐: 做程序开发的你如果经常用Redis,这些问题肯定会遇到

分布式缓存Redis是一种支持Key-Value等多种数据结构的存储系统。可用于缓存、事件发布或订阅、高速队列等多种场景。Redis使用ANSI C语言编写,提供字符串(String)、哈希(Hash)、列表(List)、集合结构(Set、Sorted Set…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 05/14 16:07
Next 05/14 16:07

相关推荐