你好,我是乔新亮。

今天,我想和你聊聊有关异常设计的话题。

如果你认真听了前面的内容,那么对你来说,异常设计应该不是一个新鲜概念了。在高可用设计、监控体系建设部分,我们都聊到了对异常的管理。

那么,为什么今天我们又要单独聊异常设计呢?因为异常管理虽然属于监控体系的一部分,但并不完全依赖于监控体系或高可用设计。在企业的监控体系建设完成前,异常设计一般就可以独立发挥作用,达到快速见效的目的。

异常管理可以提升 IT 团队快速定位问题的能力、降低生产系统异常出现的频次和数量,更重要的是,它是让 IT 团队从面向技术,转为面向产品、面向用户的关键步骤,所以我们这里独立出来讲。

那么,在开始之前,我们有必要明确一下,究竟何为异常?

你可能会想,导致系统不能正常工作的问题就是异常呗。

说得对,但不全对。有些异常,可能当下未必会对生产环境产生影响,但不代表未来也不会;有些异常,可能在流量压力小时未必会出问题,但不代表流量压力大时也不会。

就像在平时,每位同学都会打印 Log,有 Warning,有 Error。大部分同学关注 Error,而不关注 Warning ,甚至有时 Error 也是选择性忽略的。反正打印这些,也不一定会导致线上服务受影响,看看就得了。

但很可能恰恰就是这些被忽视掉的 Error 和 Warning,最终导致了严重故障的出现。

所以,所谓异常,指的就是那些让产品无法履行当初承诺用户的契约的问题。

下面,我们通过几个具体的例子来理解一下。

那些被忽视掉的异常

早些年,经常网购的同学,可能听说过电商界的两个绰号:“二手X”、“无货X”。

商品缺货、出现品质或质量问题,一直以来就是电商界的两大“顽疾”。但严格地说,这些都是因仓储系统、订单系统、质量监测系统不够完善,而导致在业务运营层级发生的概率性问题,并非研发同学心目中的“恶性故障”。

但随着用户规模的增大,原本“不值一提”的低概率问题就会被无限放大。举个例子,一家电商平台缺货的概率可能只有 2%,也就是说,配货成功率高达 98%,看起来没啥问题。但当平台用户数量达到一百万时,就会有多达两万人受到缺货问题的困扰。这两万人中,可能只有 30% 的用户有在社交平台发帖的习惯。可即便如此,也会有 6000 人出现在各大社交平台上,发帖吐槽该电商平台的缺货、质量问题。

“好事不出门,坏事传千里”,于是,“无货 X”、“二手 X”的绰号就出现了,企业声誉严重受损,用户对企业的信任也极大降低,企业需要付出更大的努力来赢回用户。

所以,许多你不太关注的异常,最终会在产品层面对用户体验产生恶性影响。一般情况下,产品经理对这类问题的感知更敏锐,但职能型研发组织中的产品经理往往不参与代码编写,一般也不会深度参与开发过程;对于程序员来说,通常也不会主动和产品经理沟通类似问题。

于是,这类问题往往会顺利通过开发、测试,最终进入生产环境。在没有异常设计的情况下,让用户买单。那些用户经历的坏体验,对于开发人员来说,可能只是一个简单的错误提示而已。

当然,这是业务和产品层面的异常。对于很多普通技术人来说,对于底层技术层面的异常,可能更为熟悉。

我曾听一位做 C++ 服务器开发的同学,讲过他们企业发生的趣事。他们经常会处理许多到不同 CDN 节点的高频下载请求,但会有一部分下载超时或耗时增加的异常出现。

他们当时的做法是,当下载耗时超过 200ms 时,在 Log 中打印 Warning ;当下载因超时而失败时,设置定时重试,并在 Log 中打印 Error 。

我好奇地问,然后呢?

他回答,然后就没什么啦,重试一般都能成功。

我继续问,如果一直不成功呢?

他挠挠头,那可能就会导致业务出问题了,研发就得起床查 Log 了。

我又问,如果重试可以成功,但当并发压力增大时,来不及多次重试呢?

他尴尬地笑了下,没说话。

你看,往往我们在做所谓的“异常设计”时,并没有实现给用户的契约。对于电商平台而言,没有实现“成功下单 = 成功配送”的契约;对于那位做 C++ 服务器开发的同学来说,没有实现给其他系统模块的“准时下载”的契约。

大家通常认为,当下的异常没有导致生产环境出现严重问题,所以以后也不会出问题,但实际情况往往不是这样。

在我看来,没有兑现契约,即为异常,就应该控制起来。

那么,到底怎么做好异常设计呢?我们大致可以分为三部分来理解,分别是认知、方案和治理。

对于异常设计的认知、方案和治理

首先,对于异常设计,有五点认知一定要明确,分别是:

  1. 异常一定要消灭:有异常,基本就意味着系统存在风险,一定要消灭异常;
  2. 异常一定要管理:消灭异常是个长期工程,短期要通过管理行为来进行控制;
  3. 对异常的处理水平,会极大影响产品的用户体验:用户规模越大,异常的影响往往越大;
  4. 每个异常都要有具体的负责人:没有和具体的负责人一一对应,往往就意味着管理流于形式;
  5. 与终端用户相关的异常,要以最高优先级处理:即便是 IT 研发,也要以用户为中心。

有了对异常的正确认知后,我们就需要在体系上对异常进行管理。

前面,在高可用设计部分,我曾经分享了“交易体系”和“协同体系”的设计差别。简单来说,交易体系负责处理相对稳定的业务流程,协同体系则是当异常出现时,需要接入的流程。比如客户要订 500 斤白菜,由交易体系来完成,库存满足、正常履行;库存不足时,则需要协同体系完成剩余流程。

但很多同学只做交易体系,不做协同体系,只抛出异常,而不处理异常,因此常常会引领用户走上“断头路”。在某些情况下,用户无路可走,只能找客服投诉。

认知到位后,下面我们一起来看如何落实异常设计。异常设计一般包含异常注册、异常事件触发、异常协作流程以及异常统计。

要管理好异常,我们首先要完成对异常的注册,注册内容大概分为以下几项:

  1. 异常的 ID 和名字;
  2. 对异常的描述;
  3. 异常出现的代码位置;
  4. 负责此异常的研发、测试和产品人员;
  5. 异常发生时的代码版本;
  6. 当时使用的异常处理程序。

同时,企业也要建设异常中心,各个系统都要在异常中心注册异常,一旦运行阶段出现异常,就要抛出异常事件,触发异常处理的协同流程。

当然,很多企业在还没有很好地管理异常时,就已经建设了大量的系统,因此很难再做异常设计。但很多异常都被记录在了日志里,因此研发同学可以通过收集日志中的异常,继而进行归类处理,再通过异常治理完成异常的注册,这样就间接达到了目标。

异常注册、收集后要做什么呢?当然是交由相关负责人进行处理了,这时我们就进入了异常的治理流程。不是所有的异常都要从 Log 中消失,但对于保留下的异常,一定提交管理层进行审批,说明保留原因;理由不够充分的,需要按排期规划并解决。

比如到 CDN 节点的下载行为有一定概率会失败,我们就要调查究竟是服务商提供的节点有问题,还是系统程序在编写方面有问题,又或者是相关机房的网络情况不好。总之,问题一定要明确并解决掉。

管理层也要关注异常的处理情况,包括:

  1. 异常的数量;
  2. 异常的发生频次;
  3. 系统内异常数量的增速或降速;

……

在季度末、年末,我们会对管理层进行绩效考核,并将异常管理情况纳入考核体系,以此实现异常治理的闭环。

你可能会想,写个代码可真难啊,越来越麻烦了。不要怕麻烦,要关注投入产出比。做好异常设计,我们既可以做到高可用、高可靠问题的防微杜渐,还可以帮助研发和测试人员快速定位 Bug。最重要的是,在企业层面,我们可以实现用户体验驱动内部经营完善的经营逻辑。对于一个技术人来说,这无疑是能帮助你上台阶、再成长的。

在苏宁的时候,我主导研发了“神鉴”系统,目标就是为了做好企业的异常管理。在彩食鲜,我们也在不断完善异常管理,虽然时间不长,但相关工作已经卓有成效。前几天,相关人员还汇报道,我们科技中心所有产品的异常码都已经被统一管理起来,相关异常编码、响应信息都会被实时收集、归类,保证可视化、可统计。

你看,当我们能把繁杂的技术细节,纳入体系化的管理流程里时,还有什么样的困难我们克服不了呢?

当你用这种思路去管理异常时,就可以对一家企业有更深入、更近距离的了解。只要仔细观察一家企业是如何对待异常的,就可以判断这家企业的精细化运营和管理水平。

结语

今天,我们聊了聊与异常设计相关的话题,最终的目的,是让企业的潜在产品和研发问题,全部暴露出来,达成最好的产品体验。

但在落地异常设计时,也一定不要着急。要知道,异常,是会和我们长期共存的,对异常的处理和记录,也会逐渐成为企业数字资产的一部分。

对于直接影响用户体验的问题,要有契约精神,快速迭代;对于企业宏观角度的异常治理,要坚持长期主义,不断优化。

此外,企业的一个核心竞争力就是持续进化的能力。因此,在保持进化的过程中,企业发生的任何问题,都要纳入到异常管理流程中,将异常管理数据化、产品化、系统化,通过持续的治理和数据分析,让企业不断进化,最终建立竞争优势。

相信你一定能将异常管理做得越来越好,让一切错误无所遁形。

我们下一讲再见!