1. 为什么要平台化:某公司基础架构的失控现场
先讲一个我印象特别深的凌晨三点。
当时某公司内部已经有二十多个核心业务系统,用户量涨得很快,线上告警也越来越多。那天晚上支付成功率突然掉了三个百分点,几个研发分别登录各自的服务器查日志。A系统的人说“我这边客户端连不上B系统”,B系统的人说“我这边收到一堆格式不完整的请求”,C系统的人说“我查了日志,凌晨两点半开始就有超时”。每个人都觉得自己没错,但谁也没法证明到底是谁错了。最后还是靠几个技术骨干拉群,把各自的日志文件截图拼在一起,一点点对时间戳,花了四个小时才定位到一个下游服务的连接池泄漏。
那个晚上之后,我意识到一个问题:这家公司的技术栈不缺人才,不缺系统,但缺一个把“协议、监控、日志、诊断”串起来的中枢。说白了,就是缺平台化。
这篇文章想聊的就是我们团队过去十年做平台化演进踩过的坑、走过的弯路和沉淀下来的方法论。不管你是基础架构的负责人,还是刚接手公司技术平台的工程师,只要你所在的组织正处于“系统很多、排查靠人海战术”的阶段,这篇文章应该能给你一些参考。
平台化不是一个新概念,但很多人对它的理解停留在“把公共能力抽出来做成服务”。实际上,平台化最难的不是技术,而是四个维度——协议、监控、日志、诊断——如何从“各自为政”走向“有机协同”。这四个维度恰恰是线上问题从发生、发现、定位到解决的全链路必需品。
接下来我按照这四条线,讲讲我们的十年演进过程。
2. 协议标准化:让所有系统说同一种语言
2.1 早期混乱:每个团队都有自己的“方言”
先说说协议这件事。它是平台化的地基,也是最容易被忽略的。
2014年那会儿,某公司的服务间调用方式五花八门。Java服务之间用某RPC框架,Python服务之间走HTTP+JSON,PHP服务直接调用数据库表,还有一些老系统保留着自定义的TCP私有协议。每个团队都觉得自己选型没问题,但跨团队联调时问题就出来了。
最典型的场景是:A团队的接口返回的code字段是数字,B团队的接口返回的code字段是字符串,前端同学对接的时候要写一堆兼容逻辑。更麻烦的是消息队列的消息格式,有的发JSON,有的发二进制序列化对象,C团队接D团队的消息时,得先花两天看对方的文档、写解析代码。
这个阶段,排查线上问题有多痛苦我都不想说。一个请求从客户端到服务端,经过五六个系统,每个系统打日志的格式都不一样,有的带traceId,有的不带,有的用UUID,有的用时间戳加随机数。出了问题只能顺着调用链挨个系统翻日志,定位一个bug经常要半天。
2.2 第一个转折点:统一协议头的强制规范
我们做的第一件事不是推一套多牛逼的RPC框架,而是先定义了一个统一的协议头规范。
这个协议头不承载业务逻辑,只承载三件事:身份标识、时间、链路轨迹。具体来说,每个请求和消息必须包含:
traceId:全链路唯一的追踪ID,由入口网关生成,透传所有下游timestamp:客户端发起时间,精确到毫秒sourceSystem:来源系统标识targetSystem:目标系统标识uid(可选):登录用户标识,用于用户维度的排查
刚开始推这个规范时阻力很大。很多团队说“我们服务内部不需要traceId,响应快得很”,还有团队认为这是增加额外字段、浪费带宽。我们的做法是先拿数据说话:挑了一个告警频繁的服务,在它的调用链路上临时加了一个中间件,统计一条请求从入口到出口平均经过多少个节点、每个节点的耗时分布。
结论很直观:平均一个请求经过6.8个节点,耗时最长的节点占比高达45%,但单个节点本身并没有慢。也就是说,问题出在链路,而不在节点。没有traceId,你就永远看不到链路全貌。这个数据在技术委员会上一摆,统一协议头规范就通过了。
2.3 什么是好的协议设计:传输、序列化、服务定义三层分离
统一协议头只是第一步。后来我们在实践中总结出一个协议设计的核心原则:三层分离。
- 传输层:负责数据怎么走。我们早期用的是TCP长连接,后来逐步过渡到HTTP/2和gRPC。传输层只需要关心连接管理、超时控制、流量控制。
- 序列化层:负责数据怎么编码。我们最终统一用了Protobuf,不单纯因为它性能好,更关键的是前后端加字段时可以向后兼容,不会出现“对方加了个字段我这边就解析失败”的经典事故。
- 服务定义层:负责接口长什么样。这层是给人和IDL用的,必须要有版本管理。
这三层各管各的,升级任何一层都不影响另外两层。比如我们后来从HTTP/1.1切到HTTP/2时,序列化层和服务定义层完全没动,业务方只需要改一行配置。
2.4 协议标准化的实战细节:字段命名与兼容性
很多人觉得写个规范文档很容易,真正落地难。这里分享三个我们在实战中踩过的细节坑。
第一个坑:字段命名风格不统一。有的团队用user_name,有的用userName,下游解析时还要写两层映射。我们最终在规范里硬性规定:跨服务传输的字段一律用下划线命名,内部变量用驼峰由各语言各自处理,中间的转换交给序列化层。这种“层次解耦”的思路,比单纯追求某一种命名风格更实用。
第二个坑:布尔字段的“三态问题”。很多接口里有个is_success字段,早期是布尔类型,后来业务方说需要区分“失败但重试有效”和“失败且不能重试”,于是改成了整数。这种变更如果是通过新增字段解决,就不会影响老调用方;但当时直接在原字段上改类型,导致所有下游都跟着发了一版。
这给我们一个教训:协议字段一旦发布,语义就冻结了。任何变更都应该是新增可选字段,而不是修改原有字段的含义和类型。
第三个坑:枚举值的兼容。某个服务的状态码早期是1,2,3,后来因为语义调整,把2从“处理中”改成了“排队中”。看似一个不起眼的改动,结果让好几个依赖方展示错了状态。从那以后,我们的规范里明确一条:枚举值一旦对外暴露,只能追加,不能修改已有值的含义。
2.5 协议演进带来的直接收益
协议标准化之后,最大的变化不是性能,而是排查问题的效率出现了数量级提升。
有了统一的traceId,我们后续才可能做全链路追踪;有了统一的序列化层,我们才可能做流量录制回放、压测平台;有了统一的协议头,我们才可能在网关层无侵入地做灰度路由、流量染色、限流降级。所有这些上层能力,都建立在“所有系统说同一种语言”的基础之上。
协议层稳定之后,我们陆续把一些公共能力下沉到了协议中间件里,比如超时重试、熔断降级、连接池管理,业务方的代码反而越来越薄。这也是平台化的一个副产品:业务代码越来越专注于业务,基础设施能力越来越下沉。
3. 监控体系的演进:从“服务活着吗”到“链路还顺畅吗”
3.1 监控的三个阶段:存活、性能、链路
协议标准化让数据“可追踪”了,接下来要解决的是“可观测”。我们的监控体系演进大致分三个阶段,和很多公司走的路类似,但每个阶段的踩坑点很值得说。
阶段一:存活监控。最早的监控就是一台机器上跑几个cron脚本,定时检测关键服务的端口通不通,不通就发告警邮件。这个阶段只能回答一个问题:服务活着吗?问题是“活着”不等于“没问题”。端口通着,但接口已经超时到不可用,cron脚本是感知不到的。
阶段二:性能监控。后来我们引入了时序数据采集,每个服务上报CPU、内存、QPS、平均延迟、错误率这些基础指标。这个阶段能回答“服务健康吗”,但视角还是单机的,不知道一个慢请求到底是自身问题还是依赖的下游问题。
阶段三:链路监控。借助前面统一的协议头,我们自研了一个轻量级的链路追踪组件,把一条请求经过的所有节点、每次调用的耗时、状态码串成一条链路数据。这是质变。因为只有到了这个阶段,监控才从“看单个服务”变成“看整条链路”,才能真正回答“链路还顺畅吗”这个问题。
3.2 监控指标怎么定:RED和USE都用过,最后还是业务说了算
关于监控指标,业内经常讨论RED(Rate速率、Error错误、Duration耗时)和USE(Utilization利用率、Saturation饱和度、Errors错误)。这两种方法我们团队早期都试用过,各有道理,但落地时发现问题没那么简单。
比如一个典型的用户登录服务,用RED指标看,QPS正常、错误率为零、平均延迟也正常,但产品反馈“登录很卡”。后来追查发现是某个第三方短信服务偶发慢调用,这个调用不在登录主链路里,但对用户体验影响很大。简单来说,RED和USE方法适合基础设施层,业务层的监控指标必须从用户视角出发,反向拆解。
我们的做法是:每条核心业务链路都定义“黄金指标”,由业务方和技术平台共同评审。比如支付链路关注“支付成功率”和“支付耗时分布”,登录链路关注“登录成功率”和“登录到首屏的时间”,消息链路关注“投递延迟”和“消费堆积数”。这些指标不是技术指标,而是业务可感知的指标,但它们是通过下层技术指标聚合计算出来的。
有了业务黄金指标之后,我们再倒推每一个环节的技术指标该怎么定、告警阈值该设多少。这个顺序很重要:不要从监控平台能采到什么指标出发,而要从业务要想保证什么效果出发。
3.3 告警治理:我们是怎么把告警从600条/天降到了40条/天
告警风暴是每个平台团队都躲不开的坎。我们最疯狂的时候,一个晚上能收到600多条告警,真正需要处理的不到10条。告警太多,人就会麻木,最后变成“狼来了”:真正出大事的时候大家反而没有第一时间响应。
我做告警治理的核心方法就一句话:告警必须关联影响面,没影响面的告警不如不告。
具体怎么做?我们把告警分成三个等级:
| 等级 | 定义 | 示例 | 通知方式 |
|---|---|---|---|
| P0 | 核心链路不可用或大范围资损 | 支付成功率下降超过2%持续5分钟 | 电话+IM立即通知 |
| P1 | 非核心功能受损或核心功能劣化 | 搜索功能超时率超过5% | IM提醒+15分钟未处理自动升级 |
| P2 | 潜在隐患,暂不影响用户 | 某服务内存水位超过80%持续1小时 | 汇总日报,当日复盘 |
这里有个关键点:判断告警等级不是看“这个服务挂了”,而是看“这个服务挂了影响了谁”。所以我们把业务黄金指标和下层技术指标做了关联配置。比如下游服务不健康、导致登录链路成功率下降,这条告警自动升级为P1;但如果只是某个内部报表服务不健康,且暂不影响任何核心链路,就只记录到日报里。
落地这个机制花了两三个月,但效果非常明显:日均有效告警降到40条左右,而且每条告警都附带了影响链路、影响范围和初步定位建议,值班同学不再对着告警发懵。
3.4 监控体系落地的几个实操细节
第一个细节:埋点的标准化比监控平台本身更重要。很多人一上来就选型看板工具、选型时序数据库,其实真正决定监控体系上限的是埋点。同一个指标,有的团队上报的是平均值,有的是P99,有的是P50,口径不一致的时候,看板再漂亮也是无效的。
我们用了接近半年的时间,把内部所有核心服务的埋点口径统一了。所有服务必须支持上报以下几个标准字段:app_id、instance_ip、env、region、metric_name、metric_value、timestamp。另外设定了几个标准统计口径:所有耗时指标同时上报平均值、P50、P95、P99,所有错误指标必须区分业务错误和技术错误。
这里强调一个容易被忽视的细节:P99和平均值的差距,往往比平均值本身更有价值。之前我们有段时间平均耗时才20毫秒,但P99到了500毫秒,说明少数慢请求正在啃掉用户体验。只看平均值,这个问题可能永远不会被发现。
第二个细节:从“指标异常”到“原因定位”,需要一条链路走到底。只看一个指标异常,只能知道“哪里有问题”,但不知道“为什么有问题”。我们后来把监控看板和链路追踪数据打通:看板上看到某个节点的P99异常高,直接点击就能跳到该节点在这段时间内的所有链路样本,再点开一条慢链路就能看到具体是依赖哪个下游、调用了哪个方法、花了多少时间。
这套“指标—链路—根因”的下钻路径,是我们监控体系里最有价值的部分。它改变了排查问题的模式:从“自己猜+翻日志”变成了“看指标→选时间→下钻链路→定位根因”。
第三个细节:监控的盲区往往藏在异步调用里。同步的RPC调用链路追踪很好做,但消息队列、异步任务、定时任务、多线程拆分这些场景,长期以来一直是监控盲区。
我们曾经出过一次事故:一个订单超时关单的定时任务某天凌晨突然执行时间拉长到原来的5倍,但监控看板上的服务指标完全正常。原因是这个定时任务处理的是整个小时积压的订单,平时一个批次几千条,当天因为上游促销流量暴增,同一批次的订单量涨到几万条,执行时间自然拉长。
这个问题的根子在于:异步任务缺少“任务维度的ID”和“批次维度的指标”。后来我们把traceId生成逻辑扩展到了异步任务里,每个批次生成一个batchId,整个批次的执行耗时、处理成功率、消费堆积数全部上报。异步调用再也不是监控盲区。
3.5 SLO不是贴在墙上的指标,而是用来倒逼容量规划的
监控体系的最后一块拼图是SLO。我们团队在推进SLO时走过弯路:最开始把SLO当成一个Dashboard,贴几个“99.9%”的数字就完事。
后来我们意识到,SLO的价值不在“定目标”,而在“定目标之后要做什么”。我们给每个核心链路定义了SLO,比如登录链路月度可用性99.95%,然后围绕SLO做了三件事:
- 错误预算消耗预警:如果本月的错误预算已经消耗超过60%,自动触发容量评估
- 容量规划联动:每逢大促前,平台团队利用历史流量数据计算“按当前SLO要求,最核心的5条链路各需要多少冗余容量”,而不是拍脑袋加机器
- 事后复盘挂钩:每次SLO违规必须复盘,容不得“尽力而为”这样的模糊结论
做到这个粒度,SLO才真正从墙上的指标变成了工程决策的依据。
4. 日志平台的演进:从“翻文件”到“万亿级检索”
4.1 日志的底牌逻辑:最后一道防线,永远不能丢
监控的局限在于它回答“哪里有问题”,但回答不了“具体为什么”。一旦需要还原现场,日志就是最后一道防线。这是我们团队对日志的定位。
早年排查问题的方式特别原始:出事了,先拉一个工单问“谁能给这台机器的权限”,然后登录服务器,cd到日志目录,grep关键字,翻文件。那时候最怕的就是日志被rotate掉了——查了半天发现关键时间段的日志已经没了,只能凭印象猜。
后来我们分了两步走,先是“日志集中化”,再是“日志结构化”。这两步我们花费的代价都不小,但回头看非常值。
4.2 集中化日志收集的架构选型:采集端、消息管道、存储检索三层
集中化日志采集,我们的架构看起来和主流方案差不多,但有些细节是踩坑之后才加上的:
- 采集端:每台机器上部署采集Agent,尾随日志文件,将增量日志发送到消息管道。这里最大的坑是Agent的批量合并策略。早期我们用的配置是每收到一条日志就发给管道,结果采集端的CPU消耗和磁盘IO都飙得很高,还对业务进程造成了轻微的抖动。后来调整成“攒够4KB或每隔1秒发送一次”的批量策略,采集端自身开销降了80%。
- 消息管道:日志先进入消息队列缓冲,再被写入存储引擎。当业务流量暴增时,管道起到削峰填谷的作用,避免存储端被瞬时流量打挂。这里有个教训:管道一满,宁可让日志原地落盘,也不能丢日志。我们遇到过管道集群扩容不及时导致日志丢失的事故,后来在采集端增加了“管道不可用时的本地缓存”机制。
- 存储检索层:早期用ELK套件,后来因为数据量和检索性能要求升级,换成了自研分布式日志存储。这里展开讲一下我们对索引策略的调整:最开始是“每个字段都建索引”,存储膨胀得厉害;后来改成“只对关键字段建索引,正文内容走全文检索”,存储和检索性能都改善明显。
4.3 结构化日志是检索平台的地基
很多团队做日志平台都觉得最难的是存储选型、检索性能,但我们的经验是:最难的是让业务团队愿意按统一规范打日志。
我们落地了一套结构化日志规范。核心要求是每条日志必须包含:
timestamp,机器的本地时间和UTC时间都打上level,严格区分debug/info/warn/errortrace_id,和协议层透传的ID保持同一个app_id和instance_ip,定位是哪个服务的哪台实例message,日志正文简明扼要- 可选但推荐:
user_id、order_id、batch_id等业务维度字段
这里我要强调一个容易踩的坑:日志的时区问题。早期我们有段时间日志检索总是对不上时间轴,后来查到原因是部分服务器的系统时区没有设置为统一时区,导致同一时刻的事件在不同机器上打印出的时间戳差了八个小时。从那以后,我们统一要求所有日志时间戳必须带时区偏移量。
结构化日志遇到的最大阻力是惯性。很多老代码里的日志是用字符串拼接的方式打的,比如logger.error("user_" + userId + "_order_" + orderId + "_fail")。这种日志在检索平台里价值极低,想按用户ID筛都筛不出来,只能全文搜索user_123456这种字符串,性能差,语义还模糊。
我们花了很大的力气做了一次日志规范治理:给所有核心业务服务开了“新日志规范迁移专项”,每个模块必须将关键路径上的日志切成JSON格式,字段名统一。那半年工作量不轻松,但完成后,日志检索效率和准确性都提升了几个量级。
4.4 日志平台的三个高频事故:索引膨胀、磁盘打满、日志里打敏感信息
日志平台本身也是运行的系统,它同样会出问题。挑三个我们经历过的典型事故说。
第一个:索引膨胀导致磁盘打满。有一段时间我们的日志存储集群经常半夜报警磁盘使用率超过85%。排查发现是无心插柳做的“全字段索引”策略惹的祸,加上有些服务把整个请求响应体都打进了日志,一条日志能有几十KB,索引膨胀得极快。后来我们做了两件事:一是只对关键字段建索引;二是对单条日志大小做限制,超过16KB的部分自动截断。
第二个:日志Agent占用过高导致业务抖动。这个前面提过,但值得再强调一次。日志采集Agent部署在业务机器上,如果批量策略、并发数配置不合理,它就会成为一颗不定时炸弹。我们当时遇到过一个案例:一个服务白天一切正常,晚上高峰期CPU使用率突然多出10%,查了半天才发现是日志Agent在高峰期日志量暴增时疯狂刷磁盘。
第三个:日志里打了敏感信息。这个问题在法律合规之外,还会导致安全事件。我们的一条规定是:日志禁止输出任何敏感字段的明文。但由于很多团队在联调阶段为了方便把密码、密钥直接打进了日志,导致了一批泄漏事故。后来我们不仅在日志SDK层做了自动脱敏,还加了定期扫描合规的策略,凡是扫到关键字敏感字段的日志直接拒收并告警给负责人。
4.5 日志与监控、追踪的联动:该不该合并成一个平台?
很多人会问:日志平台和链路追踪平台是不是应该合并?我们的答案是:数据要打通,但产品功能上要解耦。
从数据侧,日志和链路追踪共用同一个trace_id,通过trace_id可以从链路追踪下钻到某条具体请求的完整日志流。这是我们做诊断平台的重要基础。
从产品侧,日志平台的核心能力是“关键词检索+时间范围聚合+字段过滤”,链路追踪的核心能力是“按调用链拓扑查看每次调用的耗时与状态”。这两个操作习惯非常不同,合并到一个平面里反而会让两类用户都觉得别扭。
所以我们在架构上做了一个很关键的设计:不追求“一个平台干所有事”,而是让平台之间可以跳转。在监控平台看到异常,跳到链路追踪看调用链;在链路追踪看到某条具体的请求,跳到日志平台查看这条请求在每一个系统里打印的原始日志。用户不需要记三个平台的地址,只需要掌握一条跳转逻辑。
这个决策看起来不那么“炫”,但实际使用效率比硬性合并高出很多。
5. 诊断体系:从“排查三天”到“定位十分钟”
5.1 诊断的本质:不是在找一个证据,而是拼一个时间轴
讲了协议、监控和日志,终于到了诊断这层。我们做诊断平台之前,最常见的线上排查流程是:
- 收到告警
- 上监控看板看哪个指标异常
- 登录服务器看系统状态
- 翻日志
- 凭着对代码的记忆猜可能的位置
- 再翻日志验证
这种方式在小规模时还行,但系统一多、用户量一大,就完全失效了。因为排查问题的过程本质上是在还原一条事件链:什么时间、哪个系统、哪个用户、哪条请求、经历了哪些节点、哪个节点开始出现了异常。日志里全有,监控指标里也有,但在平台化之前,没有人把它们拼成一个完整的时间轴。
5.2 诊断平台的两个核心资产:链路追踪与异常快照
我们诊断体系的核心资产只有两样:链路追踪数据和异常快照。
链路追踪数据在前面已经反复提到了。有了全链路追踪,你可以回答三个关键词:是哪个节点慢了?是普遍的慢还是只有某类流量慢?是同步阻塞还是异步堆积?这三个问题基本能覆盖80%的疑难问题。
异常快照是很多团队容易忽略的。所谓的异常快照,就是当系统检测到异常时,自动抓取这个时刻的现场信息,保存供事后分析。包括:
- 所有相关服务的线程栈快照
- JVM的GC日志和堆内存使用情况(针对Java服务)
- 最近5分钟内的慢请求链路样本
- 关键服务的最近一段时间日志切片
- 系统的网络连接数、文件描述符数、CPU负载
为什么异常快照这么重要?因为异常发生时的现场信息是转瞬即逝的。等值班同学看到告警时,线程栈可能已经恢复正常了,堆内存可能已经释放了,现场早就没了。没有现场,就只能靠推断,而推断在复杂系统里往往是最不靠谱的。
我们踩过的一个典型场景:一个服务每天下午四点准时CPU飙升,但持续时间只有四五分钟。等我们登录机器查看时,CPU已经回落了,一无所获。后来加了异常快照,把CPU超过阈值那一刻的线程栈抓下来,这才定位到是一个定时做数据聚合的线程在每天四点触发了全量扫描。没有快照,这个问题可能至今还在“间歇性出现却无法定位”的状态。
5.3 根因定位的三板斧:全链路拓扑、耗时分解、日志串联
诊断平台不是一个新的监控大盘,它提供的是三个具体的分析工具。
第一板斧:全链路拓扑。根据链路追踪数据,动态生成一张服务调用拓扑图。和那些画架构图画的节点不同,这张图是从真实流量中计算出来的,每条边上的流量大小、平均耗时、错误率都是实时数据。异常发生时,拓扑图上异常的节点会高亮标出。
第二板斧:耗时分解。挑一条典型的慢请求,按“客户端→网关→服务A→服务B→数据库/第三方”的每一跳展示耗时分布。很多时候看完这个分解图,问题已经基本明确了:是某一条下游依赖变慢了,还是服务自身的长尾拖延了,还是数据库查询真的慢。
以一条典型的支付请求为例,假设总耗时800毫秒,分布如下:
| 节点 | 耗时 | 占比 |
|---|---|---|
| 接入层网关 | 25ms | 3% |
| 支付服务自身处理 | 75ms | 9% |
| 下游账户服务 | 450ms | 56% |
| 数据库查询 | 120ms | 15% |
| 其余响应等待 | 130ms | 16% |
一眼就能看出,最大的瓶颈在账务服务这一跳。
第三板斧:日志串联。有了trace_id,从一条慢链路样本点进去,可以直接调出这条请求在所有经过的系统中的全部日志。注意是全部日志,不只是错误日志。因为在很多疑难问题里,“正常日志”里往往藏着更有价值的信息,比如一个参数在某个节点被改写、一个缓存命中在某个节点失效。
5.4 诊断体系建设的节奏:别想一口气做完智能根因分析
很多团队做诊断平台时,一上来就追求“智能根因分析”,让AI自动判断问题出在哪个环节。我们团队也有过这个冲动。
但实际落地下来,我们发现一个朴素的规律:先把“人肉找根因”的工具做到极致,再考虑让机器找根因。如果一个人通过平台十秒钟能找到根因,机器的误报只会是噪音;如果一个人用平台找根因得花半小时,那么AI的结论也只能是个参考。
我们现在能做到“定位十分钟”,靠的不是多么玄乎的算法,而是一整套“数据抓全→时间轴还原→拓扑布局→耗时分解→日志串联”的工具链。这是把好用的工具交到人的手上,而不是把人从流程里抽走。
6. 平台化十年的核心方法论:先标准、再平台、后闭环
6.1 先标准、再平台:没有标准的平台化只是“一堆系统的堆叠”
复盘这十年,我们最大的方法论总结是四个字:标准先行。
很多人做平台化的思路是:先搭一个基础设施平台,拉各团队接入,再慢慢梳理规范。这个顺序是错的。没有统一协议的平台化,就像让五个说不同语言的人住进一套房子里,房子是建了,但交流还是靠肢体比划。没有统一协议、统一日志规范、统一指标口径,监控大盘上同一指标可能出现口径不一致的情况,日志检索也无法做跨系统的聚合分析。
我们的实践路径是:先在技术委员会层面把标准定出来,不追求完美,但追求有一版可执行的基线,然后所有新建系统和存量系统的增量部分必须遵循标准。存量老系统不用一次性改造,但凡是动到对外接口、打日志、接监控这几个动作,就必须按新标准来。
有了基线之后,平台化才有意义。因为平台本质上就是把标准变成可复用的工具和自动化的能力,而不是重新造一套方案让大家继续各干各的。
6.2 渐进的演进节奏:不能一年时间推翻所有老系统
平台化最大的风险不是技术实现,而是推得太猛导致业务方反扑。
我们早期的教训之一就是有一次我们想一次性把所有老系统迁移到统一框架上,预期耗时半年,结果到第四个月的时候业务方集体抗议,理由是他们正在备战大促,承受不了频繁的框架升级和重启。那次迁移最终用了十六个月才勉强完成,而且浪费了大量人力在老系统兼容性适配上面。
后来我们调整了节奏原则:新系统直接用新标准,存量系统按“核心链路优先、边缘系统慢慢来”的顺序分批次演进。每一次迁移都要有一个清晰的收益闭环,比如“这次迁移后,这个系统的排查时效能从半小时缩短到五分钟”。要能看到进步,团队才有动力继续推进。
6.3 平台和业务的关系:平台不是取代人,而是放大人的能力
做了十年的平台,我对平台团队和业务研发的关系有个很深的理解:平台不是取代人的排查能力,而是放大人的排查能力。
我们见过很多团队做平台做到最后变成了“内卷工具”,业务方要花很多时间上报数据、填字段,却感受不到平台带来的价值。为了避免这种局面,我们定了一个原则:每次给平台加一个能力,必须同时给业务方减一个负担。比如我们上线了自动化的异常现场抓取,业务方就不需要再手动登录机器抓线程栈了;我们上线了日志规范自动校验,业务方就不用再人工检查每条日志是否合规。
这个原则听起来简单,实际执行起来很难,因为你得不断问自己一个问题:“这个平台功能是让一线的人更轻松了,还是让一线的人更累了?”答案不同,平台化的方向就完全不一样。
6.4 组织层面的坑:平台团队不能替业务背锅
最后说一下组织层面的问题,这个是很多人写技术文章不提但实际非常重要的一环。
平台团队和业务团队之间最容易出现的紧张关系是:平台团队制定标准,业务团队被迫遵守,出了问题又互相指责。我们走了弯路之后,建立了一套机制:
- 标准制定的流程中,必须有业务方代表参与评审,标准不是平台团队的“私人规定”
- 标准文档的每一条都注明“解决什么问题”,业务方如果不理解可以提出来
- 平台团队负责“能力和工具”,业务方仍然负责“业务指标和各自链路的健康”
- 每次全链路事故复盘,平台团队和业务团队一起看数据,而不是平台只丢报告
说到底,平台化是技术治理,也是组织协作。
7. 未来演进:AI诊断、服务目录与成本治理
文章写到这里,很多人可能会问:那下一个十年的平台化往哪走?我谈三个我们自己已经在探索的方向。
第一个方向:AI辅助诊断。链路追踪和日志平台积累的数据量已经非常大了,借助行为序列分析的能力,可以实现一些初步的“异常传播链”自动发现。比如某个数据库实例变慢,AI模型自动关联它影响的所有上下游请求,推演出影响半径。这是一个大方向。
第二个方向:服务目录与依赖管理。让平台除了看单条链路的运行数据外,还能回答“某个服务的所有依赖方是谁、它被多少人依赖、它的变更会波及什么范围”。我们内部已在做这类资产地图实验,针对变更前影响评估尤其有帮助。
第三个方向:成本治理。平台化做好了之后,数据量会快速增长,存储和计算成本会成为一个显著问题。如何把日志做分级存储、如何让监控指标按不同精度保存、如何在保证可观测性的前提下压缩数据成本,这些会成为平台团队持续要解决的问题。
这三个方向,我觉得最有价值的是第一个:当“人肉找根因”的工具链已经足够顺畅时,AI的价值才会显现。
最后分享一点我的个人总结。做平台化十年,最大的体会是:平台建设就像修路——修好之后,人们才会发现路真的有用,但是修路的过程总是枯燥而漫长。协议、监控、日志、诊断,这四个词听起来平平无奇,但当它们真正协同起来,那种“凌晨三点不再四处拉群拼日志”的踏实感,是任何新技术名词都给不了的。
如果你所在的公司正处于“系统很多、排查靠人海战术”的阶段,我的建议是:先别急着上先进框架,先定标准、抓埋点、统一日志,把这几个基础动作做扎实。到时候,你再看监控、日志和链路追踪的价值,可能会和我这十年看下来一样确信。