Serverless 越省事,运维越头疼?冷启动、日志丢失、采样难题到底怎么破
作者:Echo_Wish
很多开发同学第一次接触 Serverless 的时候,第一反应都是:
“终于不用管服务器了!”
不用买机器,不用配置环境,不用扩容,不用半夜起来处理 CPU 飙升。
听起来是不是很美?
但是,当系统真正上线之后,很多运维同学会发现一个现实问题:
服务器没了,问题并没有消失,只是换了一种形式出现。
以前传统架构的问题是:
- CPU 100%怎么办?
- 内存泄漏怎么办?
- 磁盘满怎么办?
- 服务挂了怎么恢复?
而 Serverless 时代的问题变成:
- 函数为什么突然变慢?
- 为什么偶尔出现一次 5 秒延迟?
- 为什么线上错误日志找不到?
- 为什么链路追踪数据不完整?
- 为什么监控看到的指标和用户体验不一样?
这就是 Serverless 可观测性的核心挑战。
今天我们聊三个最典型的问题:
冷启动、短生命周期、采样策略。
一、Serverless 最大的问题:你不知道它什么时候“出生”
传统服务是什么样?
比如一个 Spring Boot 应用:
服务器启动
|
加载 JVM
|
加载 Spring
|
创建 Bean
|
监听端口
|
等待请求
启动一次,运行几个月。
所以运维很好监控:
服务器状态
|
CPU
|
内存
|
网络
|
应用日志
但是 Serverless 不一样。
比如 AWS Lambda、阿里云函数计算、Azure Functions:
请求来了:
用户请求
|
平台创建运行环境
|
下载代码
|
初始化依赖
|
执行函数
|
返回结果
请求少的时候:
环境销毁
下一次请求:
重新创建
这就是大家经常说的:
冷启动(Cold Start)
一个简单例子
假设我们有一个 Python Serverless 函数:
import time
def handler(event, context):
start = time.time()
result = do_business()
cost = time.time() - start
print({
"cost": cost
})
return result
def do_business():
time.sleep(0.5)
return "success"
第一次调用:
函数初始化:
2秒
业务执行:
0.5秒
总耗时:
2.5秒
第二次调用:
初始化:
0秒
业务执行:
0.5秒
总耗时:
0.5秒
业务代码完全一样。
但是用户体验差了5倍。
问题来了:
如果我们只看业务耗时:
业务耗时 500ms
监控显示:
“系统很健康。”
但是用户:
“为什么第一次打开这么慢?”
这就是 Serverless 监控的第一个坑。
二、传统监控思路,在 Serverless 时代失效了
很多企业刚开始做 Serverless,会直接套传统监控方案。
例如:
监控:
服务器CPU
服务器内存
服务器磁盘
结果发现:
全部正常。
但是业务投诉:
“接口偶尔超时。”
为什么?
因为 Serverless 没有长期运行的服务器。
你的监控对象变成了:
服务器
↓
函数实例
↓
一次请求
监控粒度越来越细。
以前:
一天一个服务指标
现在:
一次请求一个生命周期
Serverless 可观测性需要关注什么?
一个完整链路应该是:
请求进入
↓
触发函数
↓
初始化环境
↓
加载依赖
↓
执行代码
↓
调用数据库
↓
调用第三方服务
↓
返回结果
所以我们需要记录:
| 指标 | 作用 |
|---|---|
| Cold Start次数 | 判断冷启动影响 |
| 初始化时间 | 定位启动慢 |
| 函数执行时间 | 业务性能 |
| 错误率 | 稳定性 |
| 调用链 | 定位上下游问题 |
| 资源消耗 | 成本优化 |
三、冷启动怎么监控?不要只看平均值
很多团队监控喜欢看平均响应时间:
例如:
接口平均耗时:
300ms
看起来很好。
但是 Serverless 最大的问题:
平均值会骗人。
比如:
1000次请求:
990次:
100ms
10次:
5000ms
平均:
149ms
非常漂亮。
但是那10个用户:
已经骂娘了。
所以 Serverless 必须关注:
P95、P99 延迟
例如:
P50:
100ms
P95:
800ms
P99:
5000ms
说明:
大部分正常。
但是极端情况严重。
代码里面也应该增加冷启动标记:
import time
is_cold_start = True
def handler(event, context):
global is_cold_start
start = time.time()
if is_cold_start:
print({
"cold_start": True
})
is_cold_start = False
result = process(event)
print({
"duration":
time.time()-start
})
return result
这样日志里面:
{
cold_start:true,
duration:2.8
}
你马上知道:
这次慢,是因为冷启动。
四、短生命周期:日志还没上传,函数已经没了
这是 Serverless 第二个坑。
传统应用:
服务运行一年
日志保存一年
但是 Serverless:
请求来了
执行3秒
结束
销毁
生命周期可能只有几百毫秒。
如果日志同步上传:
可能:
函数结束
↓
日志还没发送
↓
数据丢失
所以 Serverless 日志设计必须:
异步化
例如:
错误日志:
import json
import traceback
def handler(event, context):
try:
do_work()
except Exception:
log = {
"error":
traceback.format_exc()
}
send_async(log)
raise
不要:
业务代码
↓
等待日志系统返回
↓
结束
否则:
日志影响业务。
很多大厂现在采用:
函数
↓
本地缓冲
↓
消息队列
↓
日志平台
例如:
Lambda
↓
Kafka
↓
ElasticSearch
↓
Kibana
或者:
函数
↓
OpenTelemetry Collector
↓
Trace系统
五、采样策略:数据太多也是一种灾难
Serverless 最大特点:
调用量巨大。
假设:
每天:
10亿请求。
如果每一次:
完整Trace:
请求参数
↓
函数
↓
数据库
↓
Redis
↓
第三方API
全部保存。
成本直接爆炸。
所以必须采样。
最简单:
固定采样。
例如:
只记录10%。
代码:
import random
def should_sample():
return random.random() < 0.1
if should_sample():
collect_trace()
效果:
100万个请求
↓
保存10万个
成本下降90%。
但是问题来了:
如果错误只出现0.01%。
可能:
一次都采不到。
怎么办?
答案:
智能采样
规则:
正常请求:
采1%
慢请求:
100%采集
错误请求:
100%采集
例如:
def sample_request(response):
if response.status >= 500:
return True
if response.time > 3000:
return True
return random.random()<0.01
这才符合实际运维需求。
六、OpenTelemetry 是 Serverless 时代的重要答案
现在越来越多团队使用:
OpenTelemetry
原因很简单:
以前:
应用
|
监控平台A
换平台:
重新改代码
很痛苦。
现在:
应用
↓
OpenTelemetry
↓
任意监控平台
比如:
Prometheus
Jaeger
Grafana
Elastic
都可以接。
简单示例:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def handler(event, context):
with tracer.start_as_current_span(
"serverless-request"
):
result = business()
return result
自动生成:
TraceID:
abc123
Span:
serverless-request
Duration:
300ms
排查问题效率提升非常明显。
七、Serverless不是没有运维,而是运维方式变了
以前运维关注:
机器
↓
服务
↓
进程
Serverless之后:
关注:
请求
↓
函数
↓
调用链
↓
业务结果
运维从:
“服务器管理员”
变成:
“系统可观测性工程师”。
我的理解:
Serverless 最大价值不是“不需要运维”。
而是:
把低价值的服务器维护交给平台,把运维精力释放出来,投入到系统稳定性和业务体验上。
但是前提是:
你必须建立新的可观测体系。
否则:
服务器没了,
黑盒来了。
写在最后
Serverless 让开发效率提升了一大截。
但是它也给运维提出了新的挑战:
- 冷启动导致偶发延迟
- 短生命周期导致数据丢失
- 高并发导致监控成本爆炸
- 分布式调用导致问题定位困难
未来的 Serverless 运维,不再是谁会重启服务器。
而是谁能够回答:
“刚才那个用户为什么慢?”
“这个错误为什么只发生千分之一?”
“一次请求到底经过了哪里?”
这才是真正属于 Serverless 时代的可观测性能力。
服务器可以消失,但系统的问题永远存在。
区别只是:
以前我们盯机器,
现在我们盯每一次请求。