字节跳动 Serverless 容灾和多集群拓展实践
如果无法正常显示,请先停止浏览器的去广告插件。
1. ByteFaaS - 字节跳动 Serverless
字节跳动 Serverless 容灾与多集群扩展实践 / 阔鑫
2.
3. 自我介绍
• 2015年:在业务开发中最早接触 AWS Lambda
• 2017年:加入 AWS Lambda ,参与异步事件消费链路和函数执行环
境 Sandbox 的开发
•
2019年:作为早期成员加入字节 Serverless 团队,参与 ByteFaaS
技术栈的开发迭代
• 2021年:FaaS Native - 微服务 Serverless 化方案落地
• 2022年至今: 火山引擎 Serverless 产品 veFaaS 迭代开发
4. Agenda
• ByteFaaS - 字节跳动的 Serverless
• 字节内部大规模落地的挑战
• 挑战一:性能 - 冷启动优化与(去)中心化流量调度
• 挑战二:稳定性 - 运维手段与容灾体系
• 挑战三:可扩展性 - 底层资源弹性与共池
• Q & A
5. ByteFaaS - 字节跳动的 Serverless
技术架构,产品形态,业务应用
6. ByteFaaS 介绍
• 字节 Serverless 团队自研的基于 K8S 的云原生 Serverless 解决方案
• 多种 Serverless 计算的产品形态
• 函数计算 Function As A Service
• 在线微服务 FaaS Native
• 轻量级运行时 FaaS Worker
作为通用计算平台广泛支撑上层业务
•
• 内部业务:评论流审核、视频转码、
• 外部业务:⻜书 aPaaS、抖音云小程序
• 公有云业务:veFaaS
7. ByteFaaS 介绍
上层业务
多种 Serverless 计算形态
字节 Serverless 技术底座
基于 K8S 的底层资源管控
评论流审核
视频压缩转码
函数计算 FaaS
抖音小程序
在线微服务
FaaS Native
ByteFaaS 技术底座
资源池化/流量调度/弹性伸缩/…
K8S 资源 Provider
⻜书 aPaaS
云边一体
FaaS Worker
…
8. ByteFaaS 介绍 - 函数计算
函数实例 (Python)
Function Instance
API 网关
对象存储
消息队列
Kafka/
RocketMQ
。。。
触发
统一流量调度
def handler(event, context):
result = {
'body': json.dumps({
'message': 'Hello Word!'
})
}
函数实例
return result
(NodeJS)
Function Instance
exports.handler = async function handler
(event, context) {
return {
body: JSON.stringify({'message':'hello'}),
};
};
9. ByteFaaS 介绍 - 在线微服务
HTTP 微服务实例
POST /ping
GET /hello_world
Thrift RPC 微服务实例
微服务
Client/Mesh
触发
统一流量调度
(多协议)
// Ping Trhfit API 接口定义
struct PingRequest {
1: optional String Msg,
}
PingResponse Ping(1: PingRequest req)
gRPC 微服务实例
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns
(HelloReply) {}
}
10. ByteFaaS 介绍 - 轻量级运行时 FaaS Worker
WASM Worker 进程
Golang 函数 (Tinygo)
用户请求
触发
边缘/中心
流量接入
Rust 函数
最终一致性
GlobalKV
JavaScript 函数 (QuickJS)
hostcall API
临时缓存
宿主机
Local Cache
云边一体
持久化数据
11. 字节内部大规模落地的挑战
性能,稳定性,容灾体系,与可扩展性
12. 字节内部大规模落地的挑战 - 当前规模
• 覆盖字节内部所有业务线和中台部⻔
• 服务总数 20w+,活跃服务 2.2w
• 全球机房峰值 QPS 1.2亿
• 峰值集群 CPU 峰值利用率 60%
不同语言运行时 服务数量分布
13. 字节内部大规模落地的挑战 - 当前规模
• 覆盖字节内部所有业务线和中台部⻔
• 服务总数 20w+,活跃服务 2.2w
• 全球机房峰值 QPS 1.2亿
• 峰值集群 CPU 峰值利用率 60%
14. 字节内部大规模落地的挑战 - 性能
• 冷启动:前端应用和后端在线服务对冷启动性能的要求
• 离线服务优化:大流量消息队列消费场景
15. 字节内部大规模落地的挑战 - 性能
•
通用 FaaS 产品/解决方案的架构:
中心化流量调度网关
触发
中心化网关
bottleneck?
函数实例 (Python)
Function Instance
def handler(event, context):
result = {
'body': json.dumps({
'message': 'Hello Word!'
})
}
函数实例
return result
(NodeJS)
Function Instance
exports.handler = async function handler
(event, context) {
return {
body: JSON.stringify({'message':'hello'}),
};
};
16. 字节内部大规模落地的挑战 - 稳定性
业务维度
•
• 单实例问题以及对应的运维手段
• 限流与并发控制:保护下游服务
平台维度
•
•
多地域、多机房的容灾体系
17. 字节内部大规模落地的挑战 - 资源的可扩展性
服务维度
•
•
单个服务的弹性(业界的 Serverless 产品方案都能比较好的好解决)
租户维度
•
•
单个租户的资源弹性和资源保障
平台维度
•
•
Serverless 平台本身的资源管控并不Serverless
18. 性能:冷启动优化与(去)中心化流量调度
Serverless 老生常谈的问题,和新的解决方法
19. 什么是冷启动
没有流量的函数会被缩 0
•
•
•
函数 A 实例 (Python)
Function Instance
欠的债总是要还的
突增流量的临时应对
触发
统一流量调度
def handler(event, context):
函数 B 实例 (NodeJS)
result = {
'body': json.dumps({
Function
Instance
函数
B
实例
'message': 'Hello Word!' (NodeJS)
})
Function Instance
exports.handler = async function handler
}
(event, context) {
return result
函数 B 实例不够
临时扩容
• 思路 1:加快冷启动速度
• 思路 2:提前扩容,减少冷启动频次
函数 C 没有实例
临时启动新的实例
exports.handler
= async function handler
return
{
(event,
context) {
body: JSON.stringify({'message':'hello'}),
}; return {
body: JSON.stringify({'message':'hello'}),
};
};
};
函数 C 实例 (NodeJS)
Function Instance
exports.handler = async function handler
(event, context) {
return {
body: JSON.stringify({'message':'hello
20. 冷启动优化 - 加快冷启动速度
• 资源池化预热:节省 pod 创建开销(调度,镜像下载)
• 函数冷启动:镜像代码分离(字节 Golang 为主的微服务研发体系)
• 函数代码多级缓存
预热资源池 by WorkerManage
预热资源池
Golang
基于 K8S 的底层资源管控
预热资源池
NodeJS
K8S 资源 Provider
预热资源池
Python
21. 冷启动优化 - 加快冷启动速度
• 资源池化预热:节省 pod 创建开销(调度,镜像下载)
• 函数冷启动:镜像代码分离(字节 Golang 为主的微服务研发体系)
• 函数代码多级缓存
etc
token 租约续期
Worker
Manager
基于 K8S 的底层资源管控
Worker
Manager
Worker
Manager
资源池
资源池
资源池
资源池
Pod
Pod
Pod
Pod 资源池
资源池
资源池
资源池
Pod
Pod
Pod
Pod 资源池
资源池
资源池
Pod
Pod
Pod
Token1 Token2 Token3
22. 冷启动优化 - 加快冷启动速度
• 资源池化预热:节省 pod 创建开销
• 函数冷启动:镜像代码分离(字节 Golang 为主的微服务研发体系)
• 函数代码多级缓存
宿主机 Hos
对象存储
预热资源池
Golang
宿主机
host-pat
预热资源池
NodeJS
用户代码
解压
预热资源池
Python
FaaS HostAgent
用户代码下载
23. 冷启动优化 - 加快冷启动速度
• 资源池化预热:节省 pod 创建开销
• 函数冷启动:镜像代码分离(字节 Golang 为主的微服务研发体系)
• 函数代码多级缓存
对象存储
宿主机 Hos
预热资源池
Golang
宿主机
host-pat
预热资源池
NodeJS
用户代码
解压
预热资源池
Python
远端缓存
FaaS HostAgent
用户代码下载
宿主机 用户代码 缓存
24. 冷启动优化 - 加快冷启动速度
• 基于资源池预热,资源池具体需要留多大?
• 经验值:2% 的预热资源就足够
• 兜底路径 + 预热资源水位告警
25. 冷启动优化:减少冷启动频次
旁路指标提前扩容
•
• CPU/内存
• 消息队列堆积
函数 A 实例 (Python)
Function Instance
用户自定义
•
•
根据业务需求配置扩容时间窗口
CPU
函数 B CPU 负载过高
内存
并发
消息堆积
。。。
def handler(event, context):
函数 B 实例 (NodeJS)
result = {
'body': json.dumps({
Function
Instance
函数
B
实例
'message': 'Hello Word!' (NodeJS)
})
Function Instance
exports.handler = async function handler
}
(event, context) {
return result
exports.handler
= async function handler
return
{
(event,
context) {
body: JSON.stringify({'message':'hello'}),
}; return {
body: JSON.stringify({'message':'hello'}),
};
};
};
函数 C 实例 (NodeJS)
Function Instance
AutoScale
旁路信号,提前扩容
函数 C 消费的 Kafka 产生了堆积
exports.handler = async function handler
(event, context) {
return {
body: JSON.stringify({'message':'hello'}),
};
};
26. 离线消费性能优化
在线流量走中心化网关
函数
A A 实例
函数
函数 A 实例
实例
离线消费
•
•
•
Kafka/RocketMQ 消息
延迟不敏感,但是吞吐非常高(1.1亿+ QPS)
去中心化流量调度
•
• 将流量调度 与 路由发现剥离
• 绕过中心化网关
FaaS Gateway
中心化网关
函数 B 实例
函数
C C 实例
函数
函数 C 实例
实例
离线流量
中心化网关变成瓶颈
Pull
Kafka/RocketMQ
Consumer
27. 离线消费性能优化
在线流量走中心化网关
函数
A A 实例
函数
函数 A 实例
实例
离线消费
•
•
•
Kafka/RocketMQ 消息
延迟不敏感,但是吞吐非常高(1.1亿+ QPS)
去中心化流量调度
•
• 将流量调度 与 路由发现剥离
• 绕过中心化网关
FaaS Gateway
中心化网关
Dispatcher
路由管理
Pull
Kafka/RocketMQ
Consumer
函数 B 实例
函数
C C 实例
函数
函数 C 实例
实例
大流量消息队列 Consume
直接访问 Pod
28. 离线消费性能优化
•
•
•
在线流量走中心化网关
FaaS Gateway
路由管理组件 Dispatcher
基于 Rendezvous Hashing 的哈希分片策略
路由缓存:减少调用次数,缓解单点 failure
本地路由缓存
Func A pod1
Func B pod6
函数 A
Pod1
Func C pod8
Dispatcher 获取路由信息
Dispatcher 1
Dispatcher 2
Dispatcher 3
Func A pod1; pod2 Func D pod9; pod10 …
Func B pod6 Func E pod11; pod12; … …
Func F empty …
Func C pod7; pod8
29. Wrap UP
2
1
中心化网关
FaaS Gateway
路由管理
Dispatcher
3
资源池管理
Worker Manager
4
Kafka/RocketMQ
Consumer
热启动调用路径(常态)
函数实例
冷启动调用路径
预热实例
消息队列 MQ 调用路径
30. 稳定性:运维手段与容灾体系
业务视⻆和平台视⻆的稳定性建设
31. 稳定性 - 业务运维手段
业务运维手段
•
• 单实例问题:实例的概念暴露给用户(监控、运维)
• 自动化运维:单实例熔断/迁移
• 弹性的限制:限流、反压、并发控制
32. 稳定性 - 业务运维手段
业务运维手段
•
• 单实例问题:实例的概念暴露给用户(监控、运维)
• 自动化运维:单实例熔断/迁移
• 弹性的限制:限流、反压、并发控制
33. 稳定性 - 业务运维手段
业务运维手段
•
• 单实例问题:实例的概念暴露给用户(监控、运维)
• 自动化运维:单实例熔断/迁移
• 弹性的限制:限流、反压、并发控制
中心化决策
Coordinator
⻓时间熔断
单实例问题上报
单实例迁移
Func
Func
Func
触发器
系统错误
单实例熔断
Func
34. 稳定性 - 业务运维手段
业务运维手段
•
• 单实例问题:实例的概念暴露给用户(监控、运维)
• 自动化运维:单实例熔断/迁移
• 弹性的限制:QPS 限流与并发控制
Coordinato
中心化限流控制
消息队列
Consumer
消息队列
Consumer
Func
Func
Func
Func
Func
Func
Func
Func
访问下游
下游其他服务
35. 稳定性 - 平台容灾体系
全球多区域(Region)部署
•
•
Region 与 Region 之间不共享数据
同区域多集群单元化部署
•
•
降低单集群爆炸半径
同单元多 AZ 容灾
•
•
跨 AZ 流量调度
36. 稳定性 - 平台容灾体系
全球多区域(Region)部署
•
•
Region 与 Region 之间不共享数据
同区域多集群单元化部署
•
•
降低单集群爆炸半径
同单元多 AZ 容灾
•
•
跨 AZ 流量调度
37. 稳定性 - 平台容灾体系
us-east cn-north sg
控制面 API 控制面 API 控制面 API
ByteFaaS
系统组件 ByteFaaS
系统组件 ByteFaaS
系统组件
底层 K8
容器调度平台 底层 K8
容器调度平台 底层 K8
容器调度平台
38. 稳定性 - 平台容灾体系
全球多区域(Region)部署
•
•
Region 与 Region 之间不共享数据
同区域多集群单元化部署
•
•
降低单集群爆炸半径
同单元多 AZ 容灾
•
•
跨 AZ 流量调度
39. 稳定性 - 平台容灾体系
• 爆炸半径
• 重保业务
cn-north
控制面 API
ByteFaaS
系统组件 ByteFaaS
系统组件 ByteFaaS
系统组件
底层 K8
容器调度平台 底层 K8
容器调度平台 底层 K8
容器调度平台
40. 稳定性 - 平台容灾体系
全球多区域(Region)部署
•
•
Region 与 Region 之间不共享数据
同区域多集群单元化部署
•
•
降低单集群爆炸半径
同单元多 AZ 容灾
•
•
跨 AZ 流量调度
41. 稳定性 - 平台容灾体系
• 常态泳道化流量调度
• 容灾跨 az 场景切流
七层负载均衡
Gateway AZ-A
常态流量
同 AZ 调度
Gateway AZ-B
容灾场景
跨 AZ 切换
常态流量
同 AZ 调度
K8S 容器调度平台
Func
AZ-A
Func
Func AZ-A
AZ-A
Func
AZ-A
Func
Func AZ-A
AZ-B
42. 可扩展性:底层资源的弹性与共池
资源弹性的三级火箭
43. 可扩展性 - 三个层面的资源弹性
• 服务级别:突发流量冷启动 + 异步扩容防突增
• 租户级别:单体大租户对资源弹性的需求
• 平台级别:平台本身的资源弹性与计算资源的共池
44. 可扩展性 - 服务级别
•
服务级别:突发流量冷启动 + 异步扩容防突增
函数 A A A 实例
实例
函数
函数
实例
(预热资源池)
突发流量
中心化流量调度
临时冷启动扩容
函数 B 实例
AutoScale
函数 B CPU 负载过高
函数
C C 实例
函数
函数 C 实例
实例
监听旁路信号,提前扩容
函数 C 消费的 Kafka 产生了堆积
45. 可扩展性 - 租户级别
• 常态预留 10% 的水位不够(帕累托法则/二八效应)
• 单体大租户对资源/SLA的的强需求
• 对小租户的保护(防止资源断供)
46. 可扩展性 - 租户级别
• 单体大租户独占资源池
• 减少人工运维 -> 节点池弹性伸缩
K8S 集群
(火山容器服务 VKE)
公共租户节点池
大租户独占节点池
ECS 节点
ECS 节点
ECS 节点
Func ECS 节点
Cluster Autoscal
节点池负载弹性伸缩
Func
Func
Func
Func
Func
ECS 节点
Func
。。。
ECS 节点
Func
ECS 节点
Func
47. 可扩展性 - 平台级别
• 问题:用户服务实现了 Serverless,平台自己的资源管控不够 Serverless
• 宿主机节点管理的负担
• 资源断供⻛险
• 资源成本的权衡
• 资源弹性的 Gap
• ECS 虚拟机:分钟级别
• FaaS Function:百毫秒级别
• ??
48. 可扩展性 - 平台级别
• 容器服务 - 弹性容器 https://www.volcengine.com/docs/6460/76908
• 基于 Virtual Kubelet 的资源调度抽象 - Virtual Node
• 运行时隔离 + 网络隔离
• 秒级别容器启动速度
• 小规格碎片化资源的价格优势
K8S 集群
(火山容器服务 VKE)
ECS 节点
Func
Func
Pod
Virtual Nod
虚拟节点
ECS 节点
Func
Func
Pod
Pod
Pod
Pod
Pod
Pod
共享物理机资源池
49. 可扩展性 - Combined Together
•
在三个级别上实现弹性
K8S 集群
(火山容器服务 VKE)
公共租户节点池
大租户独占节点池
ECS 节点
ECS 节点
ECS 节点
Func ECS 节点
Cluster Autoscal
节点池负载弹性伸缩
Func
Func
Func
Func
Func
ECS 节点
Virtual Nod
虚拟节点
Func
。。。
ECS 节点
Func
ECS 节点
Func
Func
Func
Func
Func
Func
共享物理机资源池
50. 想了解更多
更多内容,欢迎购买字节跳动 Serverless 团队刚刚出版的
《Serverless 核心技术和大规模实践》
也欢迎关注 字节跳动云原生 了解更多云原生技术动向
51.