布景

每天在世界各地都有海量用户在短视频 App 上分享充满构思的视频或是生活中的精彩故事。

因为运用者地点的环境不可控(高铁、电梯等弱网环境),若直接播映原始画质的视频,或许导致观看影片的进程中出现卡顿乃至无法播映的景象,导致观影感触不佳。为了让不同网络条件的运用者,都能顺利地观看这些视频,每一条视频的发布,都需求经过转码的进程,生成不同档位的视频,即便用户在网络欠好的环境中,也能供给合适档位的视频,让运用者有顺利的观影体验。

针对视频转码的场景,现在业界通用的解决方案大多为原始视频上传到物件贮存后,通过事情触发媒体处理进程,当中或许触及运用作业流体系做媒体处理使命的调度或是编列,处理完结的视频存档至物件贮存后再透过内容分发网络(Content Delivery Network,CDN)分发给观影者。

短视频媒体处理系统应急响应自动化实践

图 1:媒体处理体系在 AWS 公有云上的业界通用解决方案

[来历]https://aws.amazon.com/media-services

在业界通用的公有云解决方案中,对开发者而言需求整合公有云上各个子体系,来完结视频转码的生命周期,以及办理虚拟机核算资源,这需求较大的认知成本以及对各种云服务的学习成本,对开发者来说是比较大的负担。

在字节,视频架构团队经过长年的技能积累,在视频这个领域已经形成了一个内部多媒体处理 PaaS 渠道。用户通过上传体系上传视频到物件贮存中,接着会触发媒体处理渠道的使命编列体系,下发转码、生成动图、封面照等使命到具有海量资源的核算资源池,终究透过内容分发网络分发给观影者。多媒体处理 PaaS 渠道首要由两大子体系构成,作业流体系与核算渠道,并供给多租户的接入方法,用以支撑字节整个生态系的视频处理需求。

核算渠道首要供给了一个大型的核算资源池,将各种异构资源(CPU、GPU)封装起来,让团队内媒体处理专业的开发者无需重视核算资源整合相关作业,能够专心于开发具有各种原子才能的无伺服器函数,供给转码、生成封面照、生成动图等丰富功用。作业流体系则供给了使命编列的才能,能够界说视频上传后需求履行各种媒体处理使命的先后顺序,并将使命下发到核算渠道运用大型的核算资源池来完结媒体处理的作业。

透过这两大子体系供给的根底才能,能够大大削减开发者的负担以及提高功用迭代的速度。

短视频媒体处理系统应急响应自动化实践

图 2:视频架构团队媒体处理体系解决方案

技能框架 1.0

这么巨大的一个线上体系,怎么坚持它的稳定性,而且在线上有任何反常状况时,能够准确、快速地处理问题,削减对用户的影响就显得特别重要。针对布置在世界各地的多媒体处理 PaaS 渠道都会界说服务水准目标 (SLI),并以此为根底界说服务水准方针 (SLO),并装备针对 SLO 的适当报警规则。

短视频媒体处理系统应急响应自动化实践

图 3:应急呼应流程

如图 3 所示,当服务产生反常,例如:5分钟内恳求正确率低于 99.9% 时,触发报警,并发送 Webhook 音讯给团队内研发的应急呼应中心渠道,渠道会将当下的值勤人员创建一个告警处理群组,并把后续相关的报警信息都聚合到群组中,随后就由 SRE 开端介入处理。当时流程在创建告警处理群组之后,首要仰赖 SRE 去自主搜集与应急事情相关的反常目标,缺少主动化工具提前做音讯的汇总,或许导致全体事端处理流程需求花费较多时刻先梳理现在反常的目标才能做事端止损操作。

当时的痛点

微服务及依靠数量多

在团队中,服务的开发大部分走的是微服务架构,而且作为一个内部的 PaaS 渠道,势必得供给全球跨区域的服务因而在服务自身以及根底设施方面,需求有多区域以及多机房的布置。现在只看单一区域媒体处理使命调度的微服务就有 30 个,此外还需考虑相关的根底设施的监控,如:数据库、缓存、分布式锁以及音讯队列等……

短视频媒体处理系统应急响应自动化实践

图 4:数量巨大的微服务监控仪表板

因而,即便制造了如上图全局视角的监控仪表板,但在应急事情产生的当下就能敏捷的定位如此巨大的服务拓扑中的反常点,仍然是一个具有挑战的使命。

不同目标比较基准不同

关于应急事情产生时,一般能够分为以下两种状况:根底设施反常、突发流量。

第一个比如:数据库根底设施。一般在正常运作下的查询推迟都会处于一个固定的水平,例如 10ms 。推迟上升分为:全体数据库推迟上升(或许是当下负载高),部分实例推迟上升(或许是部门网段有颤动)。

短视频媒体处理系统应急响应自动化实践

图 5:数据库推迟反常目标

第二个比如,突发流量。作为一个内部的 PaaS 渠道,势必是供给了多租户的功用以服务字节内诸多团队的需求,且当租户数量到达一个量级,逐个租户去了解他们何时有活动或是有突发流量已经是不太合乎经济效益的事情,以下方的比如为例,能够看到目标呈现以天为周期的规律分布,但能够看到红框处紫色的目标较昨日显着得更多,这称之为昨日同比上升。

短视频媒体处理系统应急响应自动化实践

图 6:流量目标同比上升

过错排查触及不同内部体系

第三个比如,触及依靠体系的过错。以下图为例,红框处的过错量显着比过去半小时要高得多,这称之为环比上升。针对这种状况则需求到内部的 PaaS 渠道去查询详细的过错码以及对应的过错日志。

短视频媒体处理系统应急响应自动化实践

图 7:依靠体系过错目标环比上升

方针

以上三种状况,以现有的监控以及排查手段,在应急事情产生时,整个排查的进程需求比对多个仪表板乃至是不停地在仪表板上切换不同的查询时刻段来比较目标的正常性,更甚者需求翻开其他内部体系来查找日志,这都大大延长了定位问题以及做应急处理的决策时刻。

因而假如能够把上面的排查作业做必定程度的主动化,那就能大大提高 SRE 成员在值勤时对照值勤手册 SOP(标准作业流程)来排查的速度,并能削减值勤的辛苦感触。

量化目标

均匀修正时刻(Mean time to repair,MTTR)包含了发现毛病(Identify)、毛病定位止损(Know)以及毛病康复(Fix)的全体时刻。导入主动化排查工具的首要意图是削减毛病定位止损的时刻,现在体系都有设定针对 SLO 方针的告警产生以及康复时刻的数据计算,因而决定以 MTTR 这个目标来作为这次主动化体系导入的成果量化目标。

短视频媒体处理系统应急响应自动化实践

图 8:均匀修正时刻在事端时刻序中的规模

架构

技能架构 2.0

短视频媒体处理系统应急响应自动化实践

图 9:改善后的应急呼应流程

视频架构稳定性团队研发的应急呼应中心渠道(Emergency Center)内建了名为 SOP Engine 的集成解决方案,供给了 SDK 让 SRE 的成员能快速开发,如:Metrics 查询、剖析、建议 HTTP 恳求等通用的无服务器函数,并能够运用 yaml 界说状态机作业流编列,来实现自界说的告警确诊或是应急处理预案的作业流编列运用。

主动化作业流规划

整个主动化告警处理流程能够概括成如下图的过程:

  1. 作业流被告警的 Webhook 触发,渠道携带告警上下文(时刻、区域),以及预先设定在作业流中的 Metrics 查询方针(为服务称号、数据库称号、音讯队列 Topic)和反常阈值
  2. 运用 Parallel Task 方法触发子作业流别离做:作业体系(CPU、Memory)、根底设施以及微服务的告警确诊
  3. 每个告警确诊子作业流中,都会经过 Metrics 查询、剖析以及成果聚合三个阶段
  4. 终究组装要发送到应急呼应群组的卡片并发送

短视频媒体处理系统应急响应自动化实践

图 10:主动化作业流内部流程

Metrics Query 函数

Metrics 查询函数规划了如下方典范的 API,能对接字节基于 OpenTSDB 建立的 Metrics 渠道,首要供给以下几种功用来大幅提升本函数的重用性。

  • Metrics 查询模板化,针对 indicator、tags、filters 都能够撰写 go template 语法并从 template_values 栏位带入值。
  • 援助一次查询多种时刻区段材料,运用 time_ranges 栏位下可界说如:30分钟前、1天、1周前等……不同时刻规模,在一次函数呼叫中悉数获得。
  • Metrics 下钻功用,在 drill_downs 栏位能够界说针对原有 tags 上再额外追加 tags 来获得如:原本查询全体服务的 CPU 运用率,再额外查询该服务每个主机的 CPU 运用率。
{
"zone":"xx",
"indicator":"service.thrift.{{.service_name}}.call.success.throughput",
"template_values":{
"service_name":"my_service_name",
"to":"redis_cache"
},
"aggregator":"avg",
"tags":{
"idc":"literal_or(*)",
"cluster":"literal_or(*)",
"to":"literal_or({{.to}})"
},
"filters":{
"cluster":"my_cluster_name"
},
"rate_option":{
"counter":false,
"diff":false
},
"start_at":"now-5m",
"end_at":"now",
"time_ranges":{
"5mago":{
"start_at":"now-10m",
"end_at":"now-5m"
}
},
"drill_downs":{
"instances":{
"top":1,
"top_aggregator":"max",
"tags":{
"host":"literal_or(*)"
}
}
}
}

Metrics Analysis 函数

Metrics 剖析函数规划了如下图的 API ,让阈值、同环比剖析乃至是针对 Metrics 中某一个 Tag 的下钻剖析,都能够定制要剖析的汇总成果(最大、最小、均匀、总和),此外比较运算子跟阈值也能够随意调整,这关于后续要修改阈值或是剖析的逻辑都供给了很大的便当性。

{
"display":{//必填
"namePrefix":"今日",//可选,显现称号前缀,默认:当时
"name":"推迟",//必填,剖析成果目标显现称号
"format":"latencyMs"//可选,剖析成果目标显现格式,不填则按原样输出,只显现到小数第二位,格式援助default,percent,latency,latencyMs
},
"summary":"avg",//必填,对哪一个汇总材料做显现及剖析sum,avg,max,min,count
"threshold":{//可选,阈值剖析
"value":4,//必填,原始数值阈值
"operator":"gt"//必填,比较运算子,援助gt,gte,lt,lte,eq,ne
},
"time_ranges_percentage_difference":{//可选,剖析不同时刻偏移材料
"5mago":{//键名,可自行指定称号
"display":{//必填
"name":"5分环比"//必填,剖析成果显现称号
},
"summary":"avg",//必填,对哪一个汇总材料做显现及剖析sum,avg,max,min,count
"precondition":{//可选,前置条件,原始metrics满足条件后才进行改变率剖析
"value":4,//必填,阈值
"operator":"gt"//必填,比较运算子,援助gt,gte,lt,lte,eq,ne
},
"threshold":{//可选,改变率阈值
"value":0.1,//必填,阈值
"operator":"gt"//必填,比较运算子,援助gt,gte,lt,lte,eq,ne
}
}
},
"drill_downs":{//可选,剖析不同下钻材料
"instances":{//键名,可自行指定称号
"display":{//必填
"name":"单实例"//必填,剖析成果显现称号
},
"summary":"max",//必填,对哪一个汇总材料做显现及剖析sum,avg,max,min,count
"threshold":{//可选,阈值剖析
"value":10,//可选,单实例原始数值阈值
"stdDiff":1,//可选,单实例原始数值与其他下钻值均匀比较标准差阈值
"operator":"gt"//必填,比较运算子,援助gt,gte,lt,lte,eq,ne
}
}
},
"filter":true,//可选,只显现有到达阈值的剖析成果
"metrics":[...]//略,Metrics查询函数回来的材料内容
}

JavaScript 履行函数

在 Metrics 聚合以及机器人卡片信息组装的过程中,不同的 Metrics 的聚合条件以及机器人卡片显现逻辑各不相同,假如别离开发会让全体函数的重用性以及开发功率下降,因而运用了 github.com/rogchap/v8go 这个套件开发了能够对输入 JSON 数据动态履行 JavaScript 的函数来处理这一系列的用途,谁叫 JavaScript 就是处理 JSON 格式数据的最好方法呢,如下,对 JSON 内的 Array 数据都能用原生的 JavaScript 做群组、排序、倒序以及映射的操作,非常便当。

{
"script":"data.flat().map(x=>x*2).filter(x=>x>5).reverse()",
"data":[
[1,2,3,4,5],
[6,7,8,9]
]
}

实际案例:MySQL 推迟确诊

下图是一个实际反常确诊的比如怎么用上述三个函数做组合,下图以 MySQL 推迟作为比如,能够看到大部分的 MySQL 推迟正常规模在 1s 以下,其间一台主机的推迟突然上升至 20.6s 这在应急呼应中是需求被主动发现出来而且是有或许形成应急事情的反常。

短视频媒体处理系统应急响应自动化实践

图 11:MySQL 推迟单实例反常

  • 查询推迟,如下方的作业流界说,只需求从 Grafana 仪表板中把用来做图的 Metrics 以及查询条件、时刻规模、下钻 tag 依照前面提到的 Metrics 查询函数的 API 界说填入就能做 Metrics 查询。
MetricQuery:
type:Task
next:MetricAnalysis
atomicOperationRef:metric_query
variables:
zone:xxx
indicator:mysql.latency.pct99
tags:
idc:literal_or(*)
db:my_database
aggregator:avg
start_at:now-30m
end_at:now
time_ranges:
1d:
start_at:now-1d30m
end_at:now-1d
drill_downs:
instances:
top:30
top_aggregator:max
tags:
host:literal_or(*)
port:literal_or(*)
  • 剖析推迟,下方的作业流界说,会在 Metrics 查询函数履行完结后履行,首要需求供给显现剖析成果的文案、Metrics 的单位、以及各项反常剖析的阈值。
MetricAnalysis:
type:Task
next:GroupResult
atomicOperationRef:metric_analysis
variables:
metrics.@:"@.data"#从查询推迟函数输出获得查询成果
filter:true
display:
name:推迟
format:latencyMs
summary:avg#全体推迟均匀超越500ms视为反常
threshold:
value:500
operator:gt
time_ranges_percentage_difference:
1d:
display:
name:昨日同比
summary:avg
precondition:#全体推迟均匀超越200ms则剖析当下推迟与昨日对比
value:200
operator:gt
threshold:#全体推迟均匀超越昨日的50%视为反常
value:0.5
operator:gt
drill_downs:
instances:
display:
name:单实例
summary:max#单一MySQL实例推迟最大超越1s视为反常
threshold:
value:1000
operator:gt
  • 分组成果,这个作业流过程相对简单,首要针对 Metrics 剖析函数的成果,以特定的 tag 做分组并排序,在这个比如里,咱们期望运用 IDC(机房)来做分组的键,因而在以下作业流界说中就把履行上述逻辑的 JavaScript 代码引进即可。
GroupResult:
type:Task
end:true
atomicOperationRef:jsrun
resultSelector:
mysqlLatency.@:"@.data"#从剖析推迟函数输出获得查询成果
variables:
data.@:"@"
script:|#针对IDCtag分组成果
data=data.map(x=>x.data).flat().groupBy(x=>x.template_values?.idc)

//排序材料并转换格式
for(constkeyindata){
data[key]=data[key].
sort((a,b)=>a.original_value-b.original_value).
reverse().
map(x=>({
...x.tags,
usage:{
current:x.value,
"1d":x.time_ranges_percentage_difference?x.time_ranges_percentage_difference["1d"]?.value:"无数据"
},
threshold:{
current:x.threshold,
"1d":x.time_ranges_percentage_difference?x.time_ranges_percentage_difference["1d"]?.threshold:"无数据突增"
"instances":x.drill_downs?.instances
}
}))
}
data

终究经过以上三个作业流的履行,能够得到以下材料输出成果,根本上有反常的 Metrics 以及确诊定论都已经结构化的方法做好分组以及过滤,并附有确诊定论,能够作为聊天机器人音讯的输入运用。

{
"mysqlLatency":{
"xx":[
{
"cluster":"xxxx",
"idc":"xx",
"threshold":{
"1d":"均匀推迟昨日同比大于:50%",
"current":"当时均匀推迟大于:1s",
"instances":[
{
"name":"mysql.latency.pct99{cluster=xxxx,dc=xx,host=xxx-xxx-xxx-001}",
"original_value":20600.546,
"tags":{
"cluster":"xxxx",
"idc":"xx",
"host":"xxx-xxx-xxx-001"
},
"threshold":"单实例最大推迟大于:1s",
"value":"单实例最大推迟:20.6s"
}
]
},
"usage":{
"1d":"均匀推迟昨日同比:62%",
"current":"当时均匀推迟:501.49ms"
}
}
]
}
}

而针对应用容器相关的目标确诊,如:CPU、Memory,或是应用自身的 Metrics 目标都是遵循相似的逻辑来编列作业流,只需替换查询的 Metrics 以及确诊的阈值即可。

收益

有了以上的主动化剖析工具,在视频架构团队的日常应急呼应流程中得到了很大的收益,在一次应急事情中,某一个 IDC 的网路产生毛病,如下图:某一个 IP 的过错以及推迟都特别高,在应急呼应处理群中主动触发的确诊都能直接把这类反常直接发现出来,就能立刻针对反常的实例进行处置操作。

短视频媒体处理系统应急响应自动化实践

图 12:主动化工具在事端群组中展示反常目标的汇总音讯

本主动化流程完好导入后计算 MTTR 缩短成效如下图,从2022年10月初开端导入到现在2023年1月底,每双周计算一次 MTTR:从初期的 70 分钟,到现在 17 分钟,整体下降约 75.7%。

总结

在面对如此大量的微服务以及品种繁多的根底设施依靠环境下要能在应急事情产生时快速做决策以及履行应急操作,除了要有相对完好的监控之外,而且平常需求收集应急呼应处理记录,才能计算出高频率产生的事情并概括出一个主动化的排查流程来缩短 MTTR。