AI Agent
Eino:用 Go 语言编写的 LLM 应用开发框架。
DeepSeek + Function Call:基于 Eino 的“计划——执行”多智能体范式实战
Go语言开发AI智能体有多丝滑?字节重磅开源Eino框架,内含保姆级教程
系统稳定性
字节跳动观测数据埋点标准化实践
稳定性平台建设思路是“事前预防、事中处理、事后复盘、事后补救/反哺事前”这四个阶段。
字节的服务/基础设施是分层建设的,包括端侧客户体验层、网络接入层、应用服务层、基础设施层、IDC/资源层等。
不同服务/基础设施层的监控方向
- 端侧客户体验层:产品体验监控,核心用户行为指标监控(vv/feed 成功率)
- 网络接入层:网络带宽监控、网络联通性监控
- 应用服务层(含搜广推等中台):服务可用性监控、应用性能监控
- 基础设施层:中间件/MQ/Cache/DB 监控
- IDC/资源层:OS 监控、网络监控、机房容量监控、硬件故障监控
系统可用性
揭秘字节跳动内部流量调度与容灾实践【上】
Trafficroute GTM 承载了字节跳动亿级流量、覆盖了大规模场景,是一款基于 DNS 的流量路由服务。From 边缘云计算团队。
一些基础概念:
- 边缘云计算:边缘云计算是一种将云计算能力扩展到网络边缘的计算模式,它将部分计算、存储和网络功能从传统的云计算中心迁移到靠近数据源或用户的边缘节点,以实现更低的延迟、更高的带宽利用率和更好的隐私保护。“边缘” 指的是相对于传统云计算中心而言,更靠近数据源头或用户终端的位置。
- AZ 间负载均衡:AZ 为 Availability Zone。
- GEO&ISP 就近访问:基于用户地理位置(GEO)和互联网服务提供商(ISP)的就近访问。
- EIP:弹性公网 IP(Elastic IP),是可以独立购买和持有的公网 IP 地址资源,能与弹性云服务器、裸金属服务器、虚拟 IP、弹性负载均衡等资源灵活绑定或解绑,以满足业务对公网 IP 地址的动态分配和管理需求。
Trafficroute GTM 介绍:
- 依托全球 1100+分布式探测节点,构建出强大的网络质量感知能力,实现了对“端-边-云”全链路流量的质量感知,从而能根据 APP 应用的实时的访问质量、节点负载和健康状况作出动态的流量调度。
- GEO-基础路由功能丰富,包括负载均衡、会话粘性和故障转移等多种特性。而 Perf-智能路由则在基础路由的基础上,进一步提供性能优先和负载反馈等智能调度能力,以满足更高层次的调度需求。
流量编排解决了什么问题:
- 流量从哪里来?基于地理位置、基于 ISP 运营商、基于流量特征
- 流量到哪里去?中心节点、边缘节点、CDN 厂商等
- 流量怎么去?负载均衡、会话粘性、故障转移
流量编排的方式:资源编排、健康检查编排、路由编排
资源编排:资源是指流量访问的终点,包括公有云的 EIP 、CDN 的 CNAME 或边缘接入点等。TrafficRoute GTM 支持用户按照业务场景对资源(地址)进行自定义分类、组合和编排,编排形成的地址池可被路由规则引用,进而打造个性化的流量调度与容灾解决方案。
健康检查编排:实现自动容灾的必要条件,TrafficRoute GTM 具备覆盖全球范围的 L3/L4/L7 健康检查功能,用户可以配置不同灵敏度的全链路监测能力,以此为自动容灾提供精准的决策支持,最终实现最快分钟级自动容灾。
路由规则编排:通过精心配置 TrafficRoute GTM 的路由(调度)规则,可以精确控制流量的来源与去向,同时在发生故障时,确保流量能够按照预设的容灾方案进行故障转移。
字节跳动的流量编排实践:
- 同城多活,异地灾备,确保业务稳定与连续。借助 GTM 的 GEO-基础路由模式,我们成功构建了 AZ 间流量负载均衡、 Region 间异地灾备、客户端 GEO&ISP 就近访问、分钟级自动容灾 4 大能力,以这 4 大能力为保障,实现了流量负载均衡、客户端就近接入、分钟级自动容灾等,确保了业务的稳定性和连续性。
- AZ 间流量负载均衡:通过编排路由规则的地址池权重,使得华北移动的客户端按照 60% vs 40%比例在 RegionA 的 AZ 之间实现了负载均衡。同时,通过打开会话粘性开关(TOB 版本待发布),使得特定的华北移动客户端始终访问同一个 EIP,实现会话保持功能。
- Region 间异地灾备:通过编排路由规则的生效地址池集合 vs 其他地址池集合,实现了当 Region A 整体故障,流量切到 Region B,实现异地容灾能力。
- 客户端 GEO&ISP 就近访问:过编排路由规则的线路 & 生效地址池集合,实现了根据客户端地理位置和运营商来就近访问服务的能力,从而确保时延最低、性能最优、体验最佳。
- 分钟级自动容灾:通过编排健康检查规则,实现了最快 1 分钟故障感知&容灾切换,3-5 分钟 90%+流量收敛的能力;且可感知全链路的故障,覆盖客户端→运营商网络→机房入口→后端服务。
- 全球多 CDN 调度,始终选用“最优” 加速厂商。
- 根据不同区域的需求,灵活选择“资源覆盖更广”或“加速性能更好”的 CDN 厂商进行内容加速,同时可在多个厂商之间权衡成本效益(基于 P95 带宽计费)。同时, TrafficRoute GTM 确保了不同区域的流量能够“就近接入”选定的 CDN 厂商,以保障接入性能。在国内,针对不同运营商采用了定制化的路由策略,避免了 ISP 间的“跨网”问题,确保网络流畅。
- 为了应对流量管理中的潜在故障,每个流量部分都配置了多个地址池(即多个厂商),以实现故障时的自动流量切换。在故障探测方面, TrafficRoute GTM 采用了智能推荐的分布式综合探测方法,确保探测点与流量来源处于同一区域,减少误判风险,并具备分钟级的故障感知和流量迁移能力。
- CDN 回源调度,保障源站可用性。字节跳动内部业务中,每时每刻都有超大规模的视频、图文、API 等流量经过 CDN/DSA 加速回到源站,因此源站的可用性至关重要。为确保源站的可用性,我们通过 GTM 将源站接入点(一般是若干 EIP)封装成回源域名,回源域名被加载到 CDN 厂商的回源配置当中。由于回源域名由 GTM 托管,因此其具备了流量负载均衡、全链路健康检查、分钟级自动容灾等能力,保证了 CDN 厂商至源站这一回源链路的高可用性。这一容灾策略与 CDN 厂商回源机制本身包含的容灾策略相融合,可构建更加健壮的回源链路,进一步确保链路的高可用性。
TODO 单元化架构在字节跳动的落地实践
单元化核心理念:将业务按照某种维度划分成一个个单元,理想情况下每个单元内部都是完成所有业务操作的自包含集合,能独立处理业务流程,各个单元均有其中一部分数据,所有单元的数据组合起来是完整的数据(各企业实际落地过程中会结合实际业务和基建情况做一些折中)。
单元化的背景:
- 资源限制:单机房受物理资源上限限制,同城多机房受地区的能评和供电等限制;
- 合规要求:全球化产品通常会面临不同地区的合规要求(例如欧盟的 GDPR);
- 容灾考虑:核心业务有城市级异地容灾需求,通过单元化方式可以构建异地单元。
单元化其他收益:
- 业务体验提升:结合就近调度,流量调度到最近的单元,从而降低请求耗时,提升用户体验;
- 成本方面:相比于异地冷备,两地三中心等传统容灾架构,各个单元都能直接承载流量,减少资源冗余;
- 隔离方面:在最小的单元范围内去做各种技术演进,能够有效控制风险半径。
异地单元化:
- 机房延迟较高。例如北京和上海之间 RTT P99 达 40 毫秒,此时跨机房请求耗时需要慎重考虑。
- 数据同步引擎不同+跨机房同步质量。数据同步需要考虑不同的存储引擎(数据库、缓存、消息队列等),不同引擎特性不一,实现成本和复杂度巨大。跨城机房间的延迟大而且是弱网环境,网络的质量很难保证,进一步导致数据同步质量保证难度大。
- 流量路由的问题:所谓流量路由也就是如何将流量调度到正确的单元问题,需要考虑在请求链路哪个环节(客户端、流量入口、内网 RPC、存储层等)、根据请求什么信息(用户 ID、地理位置等)进行用户归属单元的识别,以及如何进行走错单元流量的纠偏。
- 数据正确性问题:例如归属
单元1的用户 A 评论了归属单元2的用户 B 的抖音短视频,系统在单元1给 B 发了一个通知,但 B 查看评论的流量被按 B 的单元归属调度到了单元2,由于数据同步延迟问题,B 打开抖音后看不到评论。业务上需要感知这类同步延迟带来的正确性问题; - 成本问题:每个单元都需要有完整的业务资源以及支撑这些业务资源(计算、存储、网络)的基础设施(运维平台、观测平台等),需要综合考虑对成本的影响;异地单元化的改造落地涉及到包括基建、架构、业务多方的配合支持,需要考虑人力上的成本。
- 管理复杂度问题:随着单元的增加,不同的单元都需要管理对应的服务和基建,管理和运维的复杂性会有较大增加。
系统架构设计
火山引擎 RTC 实时媒体处理平台的技术实践
业务架构设计
字节跳动大规模多云 CDN 管理与产品化实践
性能优化
服务调用延迟降低10%-70%,字节跳动做了什么?
将强依赖关系的服务进行同机部署:
- 将频繁通信的服务 Pod 部署在同一台机器上
- 采用本地通信方式(IPC)替代网络通信,降低网络开销、减少延迟
服务亲和性的 Pod 调度问题 RASA(Resource Allocation with Service Affinity)挑战:
- 在制定 Pod 的摆放策略时,不仅需要考虑各种约束条件,还要综合考虑不同服务之间的依赖关系。在线上环境中,服务之间如同网状结构相互连接,它们需要频繁通信,这种流量关系称为“亲和性”。在这种情况下,要优化某个服务,如服务 A,常常需要重新调度多个其他亲和服务的 Pod,这不仅涉及到资源的约束(如可容纳的 Pod 数量),还要考虑不同服务 Pod 的放置比例,以确保最大化本地化流量。在这样复杂的环境中,设计一个既考虑到多种约束又能最大化本地化流量的算法极具挑战。
- 在字节跳动内部,由于线上服务数量众多、关系复杂,且各服务的 Pod 数量庞大,重调度的算法求解时间也成为一大限制(求解时间过长可能导致由于集群状态的变化而使得算法得出的部署方案无效)。在这种背景下,传统元启发式算法在处理大规模且约束条件及目标函数复杂的情况下,难以在短时间内有效地给出优质解。
微服务亲和性部署二次调度方案:
- 首先,控制器会收集集群的关键数据,包括服务列表、机器列表及流量信息等(步骤 1);
- 接着,控制器将这些数据打包并发送至算法模块(步骤 2);
- 算法模块完成求解后,会将新的 Pod 排布方案及 Pod 迁移方案回传给控制器(步骤 3);
- 最后,控制器执行 Pod 迁移方案(步骤 4)。
RASA 算法中服务分割:
- 服务分割:集群内微服务较多,对所有的微服务进行重新调度计算量大。现在依据流量图的特性,对服务进行多次分割,部分分割后的服务集合可能会被直接过滤丢弃,将原问题划分为多个规模更小的子问题。
- 主亲和性分割思想:大部分服务对间的流量非常小,合并它们的价值并不高,因此这些服务对无需纳入重调度算法考虑。例如,在一个约有 40 个微服务的小集群流量分布案例中,前五个服务间的流量就占了总流量的 95% 以上。只需考虑这五个服务的合并,就能实现大部分流量的本地化,从而显著降低问题的规模。
- 非亲和性分割:这种分割策略旨在排除不存在流量关系的服务。
- 兼容性分割:此分割旨在识别可能互相冲突或不兼容的服务,确保分割后的每个子问题包含的服务都能和谐共处。
- 均衡分割:旨在进一步减少每个子问题的规模,同时最小化由于服务分割可能引起的最优性损失,并且尝试均衡各个子问题的计算负载。
RASA 调度算法池 + 算法选择:
- 可以使用数学算法 CG & MIP 来精确求解决子问题,具体子问题的数学表达式参考文章内容
- 每个子问题的求解需要在一分钟内完成,但是子问题变量数目可能成千上万,因此采用 GCN 图卷积网络二分类器来针对每个子问题选择使用哪种数学算法来求解。
Running Example:
- 第一步:非亲和分割(Non-Affinity Partitioning) —— 移除那些没有亲和关系的微服务,因为重调度这些服务的容器不会带来收益。
- 第二步:主亲和分割(Master-Affinity Partitioning) —— 分析每个节点的流入和流出总流量,并进行排序,选出流量占比超过 90%的前几个微服务。在我们的例子中,选择了占比为 94.8%的前 6 个微服务。这一步将问题规模缩减为原来的一半。
- 第三步:兼容性分割(Compatibility Partitioning) —— 因为 X 和 Y 类型硬件的微服务不能共同部署在同一台机器上,按硬件要求进一步细分,将问题规模进一步缩小。在此示例中,原先的 6 个微服务问题被分解为两个子问题,分别包含 2 个和 4 个微服务。
- 第四步:损失最小化均衡分割(Loss-Minimization Balanced Partitioning) —— 对于仍然规模较大的子问题,例如一个包含 4 个微服务的子问题,进行最小权重均衡分割,将其细分为两个各包含 2 个微服务的子问题。
完成服务分割后,只需为这些分割结果分配适当的机器,即可形成几个独立的 RASA 问题输入(后面就是交给 GCN 去选择数学算法,再由数学算法选择机器)。通过这种多阶段分割策略,原本需要解决的 15 个微服务排布问题被有效地分解为 3 个仅包含 2 个微服务的子问题,且这些分割过程中的流量损失仅占总流量的 12%,实现了在最优性损失微小的情况下极大提升求解速度。
字节跳动百万级Metrics Agent性能优化的探索与实践
按照数据接收、数据处理、数据发送三个部分来分析 Agent 优化的性能热点。
数据接收:
- 使用 msgpack 对数据进行序列化,相对于 JSON 数据量更少。
- 反序列化时,针对字符串采用零拷贝函数。为了避免复制 string 类型数据,对 msgpack::object 进行转换的时候,不再转换为 string,而是使用 string_view,可以优化掉 string 的复制和内存分配。string_view 属于 C++ 的零拷贝函数。
- 小数据包聚合成大数据包。Agent 在接收端接收数据后投递至异步线程池解析以避免阻塞,但线上分析发现用户数据包大小不一且小包多,致使异步线程池任务数量多、单任务体积小,频繁取任务导致处理性能下降。
- SIMD 解析字符串 tag。用户打点指标 Tags 以纯文本字符串传递,旨在简化 SDK 与 Agent 数据格式,却使 Agent 需解析字符串反序列化 Tags,且因接收端用户打点 QPS 高,此成 Agent 性能热点。
数据发送:
- 压缩算法优化。使用 zlib 进行数据发送前的压缩,随着用户打点规模的增长,压缩逐步成为了 Agent 的性能热点。通过比较 zlib-cloudflare、zlib2、snaapy、bzip2、lz4、zstd 的 time、cpu、iterations、speed、ratio 来寻找合适的压缩算法。短期使用 zlib-cloudflare 替换,长期使用 zstd 替换的优化方案。
跨部门向的服务
跨部门向的服务:计数服务、数据埋点服务等等,应该都属于基础设施服务? 这种服务在设计的时候,需要考虑什么内容呢?
字节跳动观测数据埋点标准化实践
服务质量:从覆盖完整、定义统一、计量准确、面向引擎友好等维度来评估。
推动业务升级 SDK:在 Metrics SDK 需要升级到基线版本的情况下,以前的做法是在字节软件供应链安全治理平台上配置版本拦截,提醒用户升级,但是整体升级效率比较低,我们也无法跟踪用户的升级进展。因此我们联合字节软件供应链安全治理平台团队实现 SDK 自动升级功能。Metrics SDK 自动升级功能可以自动实现在当前业务代码库的代码提交期间,如果检测到对应集成的 metrics SDK 低于基线版本,则会向用户推送代码提交失败的通知,提醒用户需要主动升级到 metrics SDK 基线版本或以上的操作。
提升基础组件埋点质量:
| 层次 | 核心组件/着手点 | 埋点标准化设计思路 |
|---|---|---|
| 业务层 | Metrics 2.0 SDK | 内置统一的平台级 TagKV,提供横向跨语言、跨服务的 TagKV 统一 |
| 应用层 | 运行时指标、远程过程调用指标 | 横向上,提供统一的、跨语言的指标名定义 纵向上,对齐 Metrics 2.0 SDK 平台级 TagKV 规范 |
| 容器层 | 与调度合作,对容器指标采集 agent(TCE 调度)进行标准化改造 | 对齐 Metrics 2.0 SDK 平台级 TagKV 规范 |
- 首先,我们在 Metrics 2.0 SDK 内置定义了一套平台级 TagKV,这样所有使用 Metrics 2.0 SDK 的业务打点都会携带标准的预定义的 TagKV。这些共同 TagKV 包括:
_cluster、_psm、_pod_name、_ipv4等。 - 在应用层,挑选了对业务排障、应用观测常用且通用的两类指标(运行时、远程过程调用)进行标准化,目标是在横向上,提供跨语言、统一的指标名、TagKV 语义定义等;在纵向上,对齐 Metrics 2.0 SDK 平台级 TagKV 规范,以便于跨层关联。以运行时指标为例,其定义规范如下:
- 不同语言的指标采用统一命名约定:
runtime.{runtime}.{metric}[.{field}] - 不同语言类似含义指标采用统一命名风格:如 go、java 中统计堆对象申请量的指标都命名为
memory.allocated_bytes - 必须包含 Metrics 2.0 SDK TagKV 规范的平台级 TagKV,如
_psm、_pod_name等
- 不同语言的指标采用统一命名约定:
- 在容器层,与调度团队共同推动其 TCE 容器指标采集 agent(TCE 调度) 的指标标准化改造,指标 TagKV 对齐 Metrics 2.0 SDK TagKV 规范。
进一步提升埋点的性能和成本收益:
第一点是对各个组件使用独立租户,实现资源的隔离,保障写入稳定性和查询性能;
| 指标 | 租户名 | 集群类型 |
|---|---|---|
| 运行时 | apm.runtime | 独立集群 |
| 远程过程调用框架 | apm.rpc | 独立集群 |
| TCE 容器指标 | computation.tce | 独立集群 |
第二点是在语义明确的前提下,尽量使用多值格式定义指标,降低存储成本。以 TCE 调度指标为例,将原来 mem 相关的四个指标合并为一个多值指标的四个字段,存储成本大致可以被认为降低至四分之一。
| 原指标 | 改造后多值指标名 | 改造后多值字段 |
|---|---|---|
| tce.host.mem_total | inf.tce.host.mem | total |
| tce.host.mem_free | free | |
| tce.host.mem_available | available | |
| tce.host.mem_used | used |
服务平滑迁移
- 语义化指标替换。对原始 Metrics 打点的语义化封装;同时能识别在不同条件下应该使用哪个版本的指标以及对应的 TagKV。这两个关键能力能够促使在做数据迁移时,观测大盘和报警基本达到比较平滑的状态。
- Metrics 前缀分流。引导用户迁移到新租户比较缓慢,于是,推出了让用户无感知的被动租户迁移方案。大致思路是依据某些特定的指标前缀,主要涵盖一级 / 二级前缀,通过特定配置把这些指标分别路由到不同的新租户,并且在新租户上支持查询翻译,即便用户不修改查询租户,继续用 Default 租户查询仍能正常获取数据。
直播相关
抖音大型直播的画质优化实践
现场直播的链路简化:
码率:在数字视频或音频等数据传输或存储过程中,单位时间内所传输或存储的数据量。
画质优化方向:
- HDR 转 SDR 信号算法优化。目前大型赛事支持 HDR 设备录制,但是部分播放设备不支持 HDR。相比 SDR 信号,HDR 信号拥有更广的色域和更大的动态范围,在转换到 SDR 信号的过程中不可避免会产生一些信息损失。
- 图片/视频下采样算法。高分辨率的视频源占比日益增多,大部分视频需要在服务端进行降采样来配合自适应码率策略,因此降采样算法的优化也是提升 QoE 的关键。相同重建误差水平下可以节省 20%以上码率,而同等码率下则可以提升画质水平。
- 视频插帧。存在 1080P 25fps 的录制标准,现在消费者已经习惯高帧率的流畅视频体验,对于低帧率的视频会明显感受到画面的流畅度降低,影响用户观看体验。
- ROI 编码 + 专向数据集与模型优化。码率高,画面清晰,但需要的空间和带宽大;码率低则相反。ROI(Region of Interest,感兴趣区域)编码旨在平衡这两者的关系,通过合理分配码率,在有限的码率下尽可能提高观众主观感受到的画质。针对不同的赛事制作专用数据集,例如针对世界杯赛事,专门制作了足球场景的 saliency 数据集,通过眼动仪追踪球迷观看球赛时的关注区域得到足球比赛的专用 saliency 数据集,从而极大增加了模型的准确性。针对足球场景中显著性物体较多,显著性区域分散的特点,团队对检测模型进行了专门的优化,在保证检测速度的前提下,提高了模型的召回率和不同场景的鲁棒性,从而实现更优的主观质量。
超低延时直播技术的前世今生
略。
直播 RTM 推流在抖音的应用与优化
RTM(Real Time Media,低延时直播)是近期逐步兴起的一种以提升客户交互体验为目标的直播解决方案,它的特点是较传统的直播解决方案,端到端延时更小达到 1 秒级别,卡顿无明显负向,RTM 的网络传输层是基于 WebRTC 技术的(RTP/RTCP 协议)。
WebRTC(网页实时通信):它是一组开源的 API 和协议,涵盖了多个层次。WebRTC 中的数据传输部分主要依赖于传输层的 UDP 协议,通过 RTP/RTCP 协议来实现实时的音视频和数据传输。同时,WebRTC 还包括应用层的一些功能,如媒体流的获取、处理和展示等。例如,在进行视频通话时,WebRTC 利用 UDP 的低延迟特性,通过 RTP 协议将音视频数据从一端传输到另一端,并通过 RTCP 协议进行传输质量的监控和反馈。
综上所述,HTTP 是单纯的应用层协议,而 WebRTC 涉及到传输层和应用层等多个层次,不能简单地说它与 HTTP 在同一层。
其他内容
ByteHouse技术详解:基于OLAP构建高性能GIS地理空间能力
将 R 树 应用到 OLAP 中,赋予高性能 GIS 地理空间能力。