3、迁移前的准备:评估你的单体应用——哪些模块适合Serverless?哪些是绊脚石?

好,咱们进入正题。上一章我们聊了为什么要迁移,这一章,咱们得动真格的了——拿起手术刀,把单体应用剖开看看。

很多人一听说Serverless,就恨不得把整个系统全扔上去。我见过不少团队,上来就把核心交易系统往Lambda上一挂,结果呢?冷启动慢得像蜗牛,数据库连接池爆了,最后灰溜溜地回滚。说白了,Serverless不是万能药,它有自己的脾气。

所以,迁移前的第一步,不是写代码,而是评估。你得搞清楚:哪些模块天生适合Serverless?哪些模块是绊脚石,碰都不要碰?

3.1 适合Serverless的模块画像

我个人习惯,先看三个特征:无状态、事件驱动、间歇性高并发。满足任意两条,基本就是好苗子。

3.1.1 无状态的计算任务

Serverless的核心优势之一,就是自动扩缩容。但前提是——你的函数不能有本地状态。你想想看,如果每个请求都依赖本地磁盘上的临时文件,那扩缩容时数据怎么同步?

我在项目中遇到过,一个图片处理服务,原本是单体里的一个模块。用户上传头像,服务端压缩、裁剪、加水印。这个模块完美符合Serverless的特征:

  • 每次请求独立,不依赖上一次的结果
  • 计算密集,但持续时间短(通常几秒内)
  • 调用频率有波峰波谷(比如晚上8点用户活跃)

迁移后,成本直接降了60%。为什么?因为平时没用户上传时,函数根本不运行,不花钱。

典型适合场景:
  • 图片/视频处理(缩略图、转码)
  • 数据清洗、ETL任务
  • 定时任务(如每天凌晨生成报表)
  • Webhook回调处理
  • 消息通知(邮件、短信、推送)

3.1.2 事件驱动的异步处理

说白了,就是那种「触发-响应」的模式。比如用户下单后,需要发一封确认邮件。这个逻辑放在单体里,通常是个同步调用,用户得等邮件发完才能看到成功页面。用户体验差,还容易超时。

迁移到Serverless后,变成:用户下单 → 消息队列 → 触发函数发邮件。用户秒级响应,邮件异步发送。我做过一个电商项目,把订单确认、库存扣减后的通知逻辑全部拆成事件驱动,系统吞吐量提升了3倍。

我的经验: 事件驱动型模块,迁移成本最低。你只需要把原来的同步调用改成往消息队列里丢一条消息,剩下的交给函数处理。改动量通常不超过50行代码。

3.1.3 间歇性高并发的API

有些API,平时没人用,一到特定时间就爆量。比如抢票系统、秒杀活动、考试报名。传统单体架构,你得为峰值预留大量服务器,平时全闲着。Serverless按实际调用次数计费,完美匹配这种场景。

我记得有一次帮一个教育平台做迁移。他们的报名系统,平时每天几百次调用,报名当天峰值每秒几千次。用单体扛,得准备几十台服务器,报名结束就闲置。迁移到Serverless后,峰值自动扩容,平时零成本。嗯,这里要注意:数据库也得跟着改造,不然函数扩容了,数据库连接池撑不住。

3.2 绊脚石:哪些模块不适合Serverless?

说完了适合的,咱们聊聊那些「坑」。我曾经踩过不少,今天帮你排一排。

3.2.1 长连接和WebSocket服务

Serverless函数通常有超时限制(比如AWS Lambda最长15分钟)。你想想看,一个WebSocket连接可能持续几个小时,函数根本撑不住。而且,函数实例是无状态的,多个客户端连接没法共享内存状态。

我见过有人硬着头皮用Serverless做在线聊天室,结果连接一多,函数实例频繁冷启动,消息延迟高得离谱。最后乖乖换回了长连接服务器。

避坑指南: 我曾经尝试用Serverless做实时协作编辑,折腾了两周,发现根本行不通。后来改用WebSocket专用服务(比如AWS API Gateway的WebSocket + 持久化连接),才解决问题。记住:Serverless不适合需要保持长连接的场景。

3.2.2 状态敏感的有状态服务

这个其实前面提过,但值得单独拿出来说。任何依赖本地内存、本地磁盘、本地缓存的服务,都不适合直接迁移。

举个例子:用户登录后的Session信息。单体架构里,Session通常存在内存里。迁移到Serverless后,函数每次调用可能分配到不同实例,Session就丢了。解决方案是把Session存到Redis或数据库里,但这样一来,每次请求都得查一次外部存储,延迟上去了。

说白了,有状态服务不是不能迁,而是改造成本高。你得先做「去状态化」改造,把状态全部外置。如果业务逻辑复杂,我建议先放一放。

3.2.3 重度依赖本地资源的任务

有些模块,需要调用本地硬件或系统资源。比如:

  • 需要GPU加速的机器学习推理
  • 需要访问本地文件系统的日志分析
  • 需要绑定特定端口或IP的服务

Serverless运行在沙箱环境里,对这些资源的访问非常受限。我有个朋友,想把一个视频渲染服务迁到Serverless,结果发现函数实例的临时磁盘空间只有512MB,根本放不下原始视频文件。最后只能把文件先上传到S3,函数再从S3读取,网络开销大得吓人。

典型不适合场景:
  • 实时音视频处理(需要低延迟、高带宽)
  • 大规模机器学习训练(需要GPU集群)
  • 数据库迁移工具(需要长时间运行)
  • 依赖特定操作系统内核功能的服务

3.2.4 执行时间长的批处理任务

Serverless函数有最大执行时间限制。AWS Lambda是15分钟,阿里云函数计算是10分钟。如果你的批处理任务需要跑半小时甚至更久,那就别想了。

我遇到过,一个数据仓库的ETL任务,每天凌晨跑一次,处理几千万条数据,耗时40分钟。硬拆成多个函数接力跑?可以,但复杂度飙升。最后我们选择了保留在ECS上,只把其中几个轻量级的清洗步骤拆成了Serverless。

3.3 评估矩阵:一张表搞定决策

说了这么多,你可能觉得有点乱。别急,我整理了一张评估表,你拿着它,对着自己的模块一个个打分就行。

评估维度 适合Serverless 不适合Serverless 我的建议
执行时长 几秒到几分钟 超过15分钟 短任务优先迁移
调用频率 间歇性、有波峰波谷 持续稳定高并发 波峰波谷型最划算
状态依赖 无状态 强依赖本地状态 先做去状态化改造
资源需求 CPU/内存适中 GPU、大磁盘、特殊硬件 特殊硬件需求别碰
网络依赖 轻量级API调用 长连接、WebSocket 长连接用专用服务
启动延迟 可接受1-2秒冷启动 要求毫秒级响应 冷启动敏感模块慎入

3.4 实操步骤:如何快速评估你的单体应用

光有理论不行,我给你一套实操步骤,照着做就行。

  1. 画出现有架构图:把单体应用的所有模块列出来,标注每个模块的输入、输出、依赖关系。
  2. 标记状态属性:每个模块后面写清楚——有状态还是无状态?状态存在哪里?
  3. 统计调用模式:翻监控日志,看每个模块的调用频率、峰值QPS、平均响应时间。
  4. 识别外部依赖:每个模块依赖哪些数据库、消息队列、第三方API?这些依赖是否支持高并发?
  5. 打分排序:用上面的评估表,给每个模块打分。得分高的优先迁移,得分低的先放一放。
一个小技巧: 我习惯用Excel做这个评估。第一列模块名,后面几列是评估维度,最后一列写「迁移优先级:高/中/低」。做完这张表,整个迁移路线图就清晰了。

好了,这一章的内容就到这里。总结一下:评估是迁移的第一步,也是最关键的一步。别急着动手,先花一周时间把单体应用摸透。哪些模块适合Serverless,哪些是绊脚石,心里要有数。

下一章,咱们聊聊具体的迁移策略——是先拆后迁,还是边拆边迁?到时候见。