关于Serverless架构
最近在整理团队的部署方案时,重新审视了一遍 Serverless。这篇文章记录一下我对这种架构的理解:它解决了什么问题,背后的运行机制是怎样的,以及哪些场景适合用、哪些场景要慎重。
背景
写这篇文章的起因很简单:我们有不少低频任务——定时脚本、事件回调、偶发的文件处理——各自占着一台或半台服务器,大部分时间 CPU 是空闲的,但机器的钱和运维的时间一分不少。这类"资源常驻、负载稀疏"的矛盾,正是 Serverless 想要解决的问题。
Serverless(无服务器架构)近年来逐渐成为云计算领域的一个热门方向。它的核心理念是:开发者无需关心服务器的部署、运维和扩容,只需要专注于业务逻辑的开发。
需要说明的是,"无服务器"并不是真的没有服务器,而是服务器对开发者不可见——它们仍然存在,只是由云厂商统一调度和维护,开发者面对的抽象层从"机器"变成了"函数"。
在传统架构中,一个系统上线通常需要准备服务器、部署环境、配置网络、监控资源以及处理扩容问题,这些工作都需要额外的运维成本。而在 Serverless 架构中,这些基础设施全部由云厂商负责管理,开发者只需要编写函数代码并部署即可运行。
Serverless上云
Serverless 通常以 云函数(Function as a Service,FaaS) 的形式提供。例如阿里云函数计算(FC)、AWS Lambda、腾讯云 SCF 等。开发者只需要上传代码,当有请求触发时,平台会自动运行函数,并根据实际的调用次数和运行时间进行计费。
它的运行模型可以简单概括为一条链路:事件源触发 → 平台调度实例 → 函数执行 → 实例回收。事件源可以是 HTTP 请求、消息队列、对象存储的文件变更,也可以是一个定时器。平台收到事件后,会在隔离的运行环境(通常是容器或轻量沙箱)中加载函数代码执行,执行结束后环境会被保留一小段时间以复用,长时间无调用则被回收。
这种模式带来的最大变化是:应用可以按需运行,而不是长期占用服务器资源。
计费方式也随之改变:传统服务器按"持有时长"付费,不管有没有流量;FaaS 按"实际执行"付费,通常以调用次数和执行时间(乘以分配的内存规格)来计算。负载越稀疏,这种模式的成本优势越明显。
例如在一些业务场景中:
- 定时任务处理
- Webhook 事件触发
- 图片处理
- 数据转换
这些任务并不需要持续运行的服务器,通过 Serverless 可以在事件触发时启动函数执行任务,从而节省大量资源成本。
Serverless的弹性特性
Serverless 的一个重要特点是 自动扩缩容能力。当系统请求量突然增加时,平台会自动启动更多函数实例来处理请求;当流量降低时,又会自动释放资源。整个过程无需人工干预,并且具备天然的分布式和容灾能力。
这种弹性背后的机制,是平台把"一次调用"作为调度的基本单位:每个函数实例同一时刻通常只处理有限的请求,请求多了就横向拉起更多实例,而不是在单个实例上堆压力。因为实例本身无状态、可以随时创建和销毁,扩容和容灾就成了平台层面的常规操作,不再需要业务方自己设计。
对于一些小型项目或创业团队来说,这种模式非常友好。传统模式下即使业务访问量很小,也需要长期维护服务器,而 Serverless 按调用次数计费,可以大幅降低前期的部署和运维成本。例如阿里云函数计算(FC)目前每个月提供约 100 万次免费调用额度,对于很多小型应用来说已经足够使用。
不过 Serverless 架构也并非完美,目前仍然存在一些需要权衡的问题。
其中最常见的就是 云厂商绑定问题。在 Serverless 模式下,函数往往会深度依赖云平台提供的服务,例如 OSS、RDS、消息队列、日志系统等。当系统大量使用这些能力之后,如果需要迁移到其他云厂商,往往需要对代码进行一定程度的改造。这种绑定不只发生在代码层面——触发器配置、权限体系、日志与监控的接入方式,各家云的做法都不一样,迁移成本比想象中更分散。
另外一个比较典型的问题是 冷启动(Cold Start)。由于 Serverless 的函数通常运行在容器或沙箱环境中,当函数长时间未被调用时,平台会释放资源。当新的请求到来时,需要重新启动运行环境,这个过程就会带来一定的延迟。
冷启动的耗时大致由几部分叠加而成:平台调度并拉起运行环境、加载函数代码和依赖、执行运行时和框架的初始化逻辑。运行时越重、依赖越多,这个过程越慢——这也是为什么同样的业务逻辑,用 Java 这类需要启动虚拟机的运行时,冷启动通常比脚本语言更明显。
在 HTTP 请求或者事件触发的场景中,第一次调用函数时可能会明显感觉到响应变慢。如果业务对延迟非常敏感,可以通过购买 预留实例(预热资源) 的方式来减少冷启动带来的影响,但这样也会增加一定的资源成本——本质上是用"部分常驻"换延迟,又回到了传统模式的成本曲线上,需要根据流量特征算一笔账。
总体来说,Serverless 更适合以下场景:
- 事件驱动型应用
- 短时间运行的任务
- 不稳定流量的服务
- 初期规模较小的项目
而对于一些需要长期运行、高性能或者高度定制化环境的系统,例如大型数据库服务、持续运行的计算任务等,传统的服务器架构仍然更加适合。
踩坑与注意
结合前面的分析,如果准备把业务迁到 Serverless 上,有几点建议提前想清楚:
1)把函数写成无状态的。 实例随时可能被回收,任何写在本地内存或本地磁盘的状态都不可靠,需要持久化的数据应该放到外部存储或缓存服务中。
2)注意执行时长限制。 FaaS 平台一般对单次执行有超时上限,长耗时任务要么拆分成多个函数串联,要么考虑换用其他计算形态。
3)评估冷启动对链路的影响。 对外的同步 HTTP 接口对延迟敏感,冷启动的影响最直接;异步任务和定时任务则基本无感,可以优先迁移这一类。
4)控制对云服务的依赖深度。 完全不依赖云服务不现实,但可以在代码里把对 OSS、消息队列这类服务的调用收敛到独立的适配层,真要迁移时改造范围会小很多。
一个务实的做法是先挑一两个非核心的异步任务(比如定时清理、图片压缩)迁上去试水,跑通计费、日志、告警这一整套流程后,再评估是否扩大使用范围。
小结
总结来看,Serverless 并不是完全替代传统架构,而是一种新的计算模式。它的核心价值在于:让开发者更加专注于业务本身,而不是基础设施。
它把"按需执行、自动伸缩"做成了平台能力,代价是接受冷启动、执行时长限制和一定程度的厂商绑定。是否采用,取决于业务的流量形态和延迟要求,而不是架构本身的新旧。
随着云计算的发展,越来越多的平台开始提供 Serverless 能力。未来的系统架构也很可能会逐渐演变为:
Serverless + 微服务 + 容器化 的组合模式。
评论 / COMMENTS