ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

自动驾驶云控平台可靠性设计:数据链路与故障恢复实践

自动驾驶云控平台可靠性设计:数据链路与故障恢复实践 这两年搞自动驾驶云控数据平台最深的体会不是算法多难调而是工程侧的可靠性设计远比想象中磨人。车端感知、决策、控制做得再好只要云端到车端的数据链路上有一环抖一下路测就得停下来排查。云控平台本质上是车端的云端大脑高精地图下发、路侧感知融合、远程监控、场景数据回传、训练集沉淀这些活儿全部压在一条看不见的数据管道上。管道任何一个环节断了、慢了、乱了都会直接体现在路上的车上。这篇文章不谈算法榜单只谈可靠性设计以自动驾驶云控数据平台为背景把数据接入、计算调度、控制下发、故障恢复这几个环节拆开揉碎讲讲我实际踩过的坑和用过的方案。如果你也在做车云协同或者任何高实时性的云原生系统这套思路应该能直接拿来参考。1. 架构演进与可靠性设计思路1.1 云控平台到底在控什么很多人以为云控平台就是一辆车的远程遥控其实远不止这么简单。真正跑起来的云控数据平台要把分散在路上的车、路侧单元、边缘节点、中心云连成一张协同网。车端实时上报传感器数据、行驶状态、接管请求路侧设备上报交通参与者感知结果云端负责高精地图增量更新、全局路径规划、远程监控、策略下发以及把有价值的片段沉淀成自动驾驶数据集。早期我见过比较原始的平台就是一个单体服务车端通过HTTP长连接上报数据落库就完事。车辆规模小的时候问题不大但车一多就全乱了数据库扛不住、消息顺序错乱、命令重复下发、断线重连后状态对不上。可靠性设计在云控平台上不是可选项是决定项目能不能路测的生死线。1.2 可靠性设计的四条主线我把云控平台的可靠性拆成四条主线每条线对应不同的故障模式和应对策略数据链车端传感器数据、路侧感知数据能不能不丢、不乱地进入平台重点处理网络抖动、重复上报、数据乱序。计算链数据进入平台后感知融合、轨迹预测、决策规划这些任务能不能在预算时间内被可靠调度重点处理资源争抢、任务积压、实例崩溃。控制链云端决策指令能不能准确、不重复、不延迟地送达车端重点处理下发幂等、端到端确认、链路仲裁。运维链平台自身出问题的时候能不能快速发现、定位、恢复重点处理监控、追踪、容灾、备份。四条链路的可靠性手段完全不同但也互相耦合。比如数据链做了幂等控制链的重复下发风险就小控制链做了端到端确认运维链的故障定位就省力。规划架构的时候我习惯先把四条链的边界画清楚再逐条设计避免混在一起后哪里都做得不深。2. 数据接入层的可靠性设计从偶发断流说起2.1 削峰填谷与消息队列的取舍云控平台的数据接入场景跟普通互联网后端有本质区别。车辆在路上一跑传感器数据就是持续不断的流而且有鲜明的潮汐特征早晚高峰车队集中出车接入量能翻好几倍遇见突发路况路侧设备上报密度也会瞬间增加。一开始我用的是直连写入车端把数据打到Kafka消费者直接写数据库。看着简单但Kafka消费端一旦抖动整个链路就雪崩。后来我换成了消费者隔离模式Kafka作为削峰缓冲消费者独立部署写库动作从同步改成批量异步。从可靠性角度看Kafka的作用不是传输消息而是把瞬时高峰积蓄起来让下游以稳定速率消费本质上是给系统装了个蓄水池。这里有个取舍问题。消息队列加多了端到端延迟会提高但云控平台对数据接入的实时性要求并不是所有数据都一样。我把数据分成三个优先级优先级数据类型时延目标可靠性策略P0远程接管请求、安全策略下发端到端100ms双通道冗余、端到端确认P1感知融合中间结果、路侧数据秒级消息队列削峰、断点续传P2场景片段回传、训练数据分钟级批量落盘、顺序保证这样分下来P0走独立的低延迟专线P1和P2走消息队列互不挤占可靠性目标也因为分级而变得可量化。2.2 幂等与去重车辆数据重复上报的坑车端的网络环境远比机房恶劣得多。隧道里断网、地库无信号、跨基站切换重连这些都是常态。我最开始没把幂等当回事结果在一个P1链路里一台车因为信号抖动同一个感知片段被重传了三次下游融合模块把三个半重复的数据当成三个独立目标处理输出了一个幽灵障碍物。那次事故直接让我把幂等设计提到了最高优先级。消息队列场景的幂等核心是给每条消息一个全局唯一的业务ID消费者端按ID去重。但光有ID还不够重复消息可能落在不同分区、不同批次里去重表必须用支持唯一约束的存储。我当时的做法是车端生成UUID作为数据片段ID接入层以片段ID作为Kafka消息key保证同一ID进入同一分区消费者写库时用唯一索引做去重插入冲突则忽略对需要精确一次语义的场景引入事务性消息。这套方案跑了一阵去重率稳定在99.99%以上但因为顶不住数据量把唯一索引去重改成了布隆过滤器加白名单缓存的组合速度上去了偶发漏去重靠业务侧兜底。做这类系统永远要记得没有100%的幂等只有可以容忍的误判率。2.3 存储选型的可靠性与成本平衡云控平台的存储选型特别容易纠结因为数据结构太杂了。轨迹数据是时序数据感知目标带空间坐标日志又是文本统一放一个库里怎么都不舒服。我最终用的是混合存储架构车端轨迹和传感器序列存时序数据库按车辆ID和时间分区查询走时间范围扫描感知目标和融合结果存关系型数据库同时挂空间索引方便做GIS查询原始场景片段存对象存储用于离线训练数据集构建元数据和业务状态用传统的强一致数据库。混合存储的可靠性关键在数据同步。我踩过的坑是对象存储里的原始片段已经写了但关系型数据库里的元数据因为事务失败没提交结果数据集构建时出现大量孤儿文件。后来加了双写补偿任务定时扫描两边的差异发现不一致就补数据或清理孤儿总算是把一致性兜住了。3. 计算与调度层的可靠性设计不可能三角的破解3.1 为什么不能只依赖K8s自愈云控平台核心计算任务包括感知融合、轨迹预测、决策规划这些任务对算力要求高而且不少是GPU密集型。用Kubernetes管理计算资源是顺理成章的选择但我们早期太依赖K8s的自动恢复能力结果在路测中吃了大亏。K8s的Pod重启、节点驱逐、HPA弹性伸缩本质上都是事后恢复。Pod已经崩了、节点已经挂了调度器发现并重新拉起最快也要几十秒。而云控场景里一个决策计算任务如果在10秒内没出结果下游的车辆可能已经开过了决策点。所以我的结论是云原生可靠性不能只靠平台的自愈能力要在应用层做超时控制、容错降级和状态冗余。3.2 决策链路的超时与等级降级决策链路是典型的低延迟高价值链路。云端收到车端请求后要完成感知融合、路径规划、决策生成再把指令下发。我们当时定的目标在一些典型场景下端到端决策延迟要稳定在几十毫秒量级。有次压测某个场景决策延迟稳定在32.8毫秒左右看着数字很漂亮但压测同时注入网络抖动时P99延迟直接飙到200毫秒这个差距对汽车控制来说就是几米的距离差。解决思路是做分级降级一级降级感知融合超时直接用最近一帧融合结果跳过重新融合二级降级轨迹预测超时用匀速模型代替预测模型保证决策还能出三级降级云端决策整体超时车端直接启用本地的安全停车策略不依赖云端。每级降级都对应一个明确的质量指标下降但保证了决策链路不死。这就像人发烧到39度还能走但40度就得躺下休息一样系统也是分级响应而不是一刀切。3.3 有状态服务的多活设计云控平台里很多计算服务是有状态的。轨迹预测服务需要维护历史帧序列融合服务需要维护目标库这些状态如果放在Pod内存里Pod一重启就全没了。我处理的办法是把状态外置到分布式缓存服务实例之间通过缓存共享状态。这样任何一个实例挂了其他实例能立刻接管不用从头重新积累历史状态。但分布式缓存本身也会成为单点所以缓存层做了多副本和故障转移。这里要提一个细节状态外置后读写延迟比本地内存高。为了平衡我给不同状态设置了不同的容忍度。比如目标库状态可以容忍毫秒级延迟但决策状态不允许于是决策状态只缓存最近几帧其余全部穿透到后端强一致存储。这个取舍要讲清楚很多团队一搞状态外置就把所有东西都丢了反而把性能拖死。4. 控制下行链路的可靠性设计命令不能丢也不能乱4.1 下发通道的端到端确认下行控制链路跟数据上行链路不一样。数据丢了最多少一条记录但控制指令丢了可能造成严重后果。所以下行链路我从来不信任单一通道必须做端到端确认。实现方式是云端下发指令 - 车端收到后立即落盘 - 车端执行完成后回执 - 云端收到回执才标记指令完成。如果超时未收到回执云端会重试发送直到确认。这个机制看着简单但有几个坑重试不能无限制必须设置最大次数和退避策略否则一条指令反复下发造成车端指令风暴车端回执如果丢了云端会重试车端可能重复执行相同的指令所以车端必须做去重回执与指令的对应关系要引入会话ID不能只靠消息内容匹配。下行通道的链路冗余也很重要我在设计时让车端保持两个独立的通信连接一个走长连接用于常规指令一个走消息推送通道用于紧急安全指令。正常链路故障时紧急指令还能在另一个通道发出。4.2 仲裁与防冲突多车协同和单车管理场景里云端可能同时有多套系统给同一辆车下发指令。比如远程监控系统下发靠边停车而全局调度系统下发前方路口右转如果不做仲裁车上执行器会收到互相矛盾的指令这是完全不能接受的。仲裁机制的核心是给指令加优先级和时间戳由云端仲裁模块统一裁决车端收到指令后只执行仲裁后的最终指令不执行任何未经仲裁的中间结果。为了防冲突我还给每个指令源加了权限等级不同等级不能越权覆盖。例如安全系统的紧急指令永远优先于调度系统的常规指令。仲裁模块本身是高可用的冗余部署任何一台仲裁服务宕机流量立即切到备机不留窗口期。4.3 实时性与可靠性的权衡实时性和可靠性在控制链路里天然存在矛盾。要可靠就要确认、重试、仲裁这些都要消耗时间。要实时就要减少环节而减少环节又意味着降低可靠性。我的做法是把实时性和可靠性按场景拆开。比如远程接管场景端到端时延要求极高但容错率也很低所以我只加一次确认重试次数控制在3次以内超时即放弃本次接管并通知驾驶员接管。而策略更新场景实时性要求不高我反而加了两层确认和仲裁保证策略安全和正确。所有设计都不存在银弹关键是把需求分级分级后再确定可靠性和实时性的平衡点。32.8毫秒这个数字后面其实是很多环节的让步和取舍换来的单看任何一个环节都觉得还能更快但整体链路不允许某一环贪快牺牲别人。5. 可观测性与故障恢复5.1 全链路追踪从车端到云端的串起来云控平台链路长环节多故障定位难。早期出问题大家靠猜车端说是云端的问题云端说是网络的问题网络说是车端的问题扯皮半天。后来我全面引入了全链路追踪每个请求从车端发起到云端处理完成都生成一个TraceID贯穿所有环节。追踪日志统一采集按TraceID聚合任何一次指令下发失败都能看到它经过了哪些服务、在哪个环节停留了多久、最后在哪抛的异常。这里有个实践经验追踪不能只做服务间车端SDK也必须集成追踪埋点不然云端链路查得再细也不知道问题出在车端还是网侧。车端SDK体积会增加但换来的是故障定位效率的几何级提升非常值。5.2 混沌工程与故障演练可靠性的设计是否有效不能只在PPT上论证必须靠故障演练验证。我在云控平台上做过几轮混沌工程实践随机杀死一个K8s节点验证任务调度是否自动迁移给消息队列注入分区故障验证消费者是否能够降级消费人为制造网络丢包和高延迟验证决策链路是否触发降级策略停掉一个仲裁服务实例验证流量切换是否无感。演练结果很打脸。第一轮演练三个场景挂了两个。节点杀死是恢复了但恢复期间一个新的决策任务没有进入待调度队列直到超时才被发现。消息队列注入故障后消费者没有自动切换副本导致P1链路堆积。这些问题不演练根本发现不了都是在极端情况下才会暴露的隐性缺陷。后面我把故障演练排进了版本发布的例行流程每次发版前至少做一轮故障注入确保核心链路在单点故障下都能扛住。5.3 备份与容灾的RTO/RPO设计备份与容灾我以前很不上心觉得云原生架构本身有冗余不会丢数据。直到一次误操作删了生产库里的配置表才发现灾备设计有多重要。云控平台的容灾目标我按数据优先级分别定义轨迹和指令数据RTO小于30分钟RPO为0采用同步复制和实时备份场景片段和数据集RTO小于4小时RPO小于15分钟采用异步复制和定时增量备份日志和中间产物RTO小于24小时RPO可接受小时级采用定期快照。RPO为0是最难实现的意味着主库任何一次事务提交备库都必须同步完成。跨地域部署时网络延迟会拖慢主库性能。我当时的妥协方案是核心指令数据采用同机房双副本同步复制异步再复制到异地容灾中心。这样同机房故障可以无损失恢复整个地域灾难最多丢失秒级数据。这个方案不算完美但成本可控也比较务实。6. 实操排查方法与避坑技巧6.1 高频故障速查表云控平台运行久了很多故障是反复出现的。我整理了一个高频问题的排查表分享出来故障现象可能原因排查方法解决方案车端频繁断线重连网络信号弱、服务端连接数限制查看接入层连接监控和车端信号日志设置合理的连接超时和重连退避扩容接入层决策延迟飙高计算节点资源争抢、降级未生效查看铁三角监控CPU、内存、网络延迟给核心任务打资源配额设置严格的降级条件指令重复执行回执丢失触发重试查看端到端确认日志核对指令状态车端增加指令去重云端优化重试策略消息积压Kafka消费者处理慢、下游DB变慢查看消费者Lag监控和DB慢查询横向扩容消费者批量写库必要时降级写能力场景片段丢失对象存储与元数据库数据不一致跑双写校验任务检查孤儿文件补写或清理孤儿双写加补偿排查故障最重要的习惯是保留现场。云控平台涉及多端、多网、多云很多问题复现成本极高如果日志、Trace、现场快照没有保留基本等于白查。6.2 监控指标选哪些才不踩坑监控面板做得花里胡哨没有用要看就得看核心指标。我推荐的黄金指标组合端到端决策延迟P50、P95、P99并拆分子环节比如感知、预测、仲裁、下发消息队列Lag每个消费者组的实时未消费数量超过阈值就告警K8s节点与Pod状态不是只看Ready要监控重启次数、OOMKilled次数、热点调度情况下行链路重试率重试率超过1%就说明通道不稳定需要排查车端连接存活率平台接入车辆中活跃连接占比这个指标直接反映平台的接入质量。我吃过亏的地方在于监控指标太多导致告警疲劳真正的故障反而被淹没。后来我把告警收敛到只有三类影响核心功能的、影响数据不丢的、影响系统恢复的。其他指标全部降级为看板和周报不触发实时告警告警质量大幅提升。6.3 一些关于可靠性的个人心得做云控平台可靠性设计我最大的体会是四个字分层兜底。每一个环节都假设下游会挂、网络会断、数据会丢然后在本环节做兜底。车端假设云端不可用所以要能本地降级云端假设车端收不到指令所以要做重试调度系统假设仲裁系统可能延迟所以要设超时保护。每层都兜底整体才可靠。另外一个体会是可靠性设计不能靠纯理论推演必须靠混沌工程和故障演练去验证。系统上线前觉得万无一失往往上线第一天就给你一个教训。我自己被教育过几次后现在只要改核心链路就必然拉一轮故障演练确保任何单点故障都不会导致功能全挂。最后再说一个小技巧云控平台的日志和Trace统一采用异步上报不要阻塞业务主流程。因为可靠性设计本身也是要花钱、花性能的过度设计会把系统拖慢适度设计、层级清晰才是云控平台长期稳定运行的正解。
返回列表