写点什么

企业架构设计原则之品质均衡性(二)

作者:凌晞
  • 2024-04-10
    广东
  • 本文字数:4749 字

    阅读完需:约 16 分钟

企业架构设计原则之品质均衡性(二)

七、可观测

如何理解可观测性呢?举两个常见的例子。


案例一,一个技术团队经过 2 个月紧锣密鼓地开发,最近上线了一款社区抢购的系统,并且可以支持好友分享。经过一个星期的在线运营之后,整个项目组坐到一起,准备对上线一周的整体表现进行拉通和总结,并讨论下一步的产品方案和运营手段。大家落座以后,领导问运营经理每天的订单数、客单价、最热门的商品,运营勉强回答得上来;之后领导问产品经理,PV/UV 分别是多少,哪些页面用户感兴趣,哪些页面基本无人问津,用户使用最大的功能是哪一个,哪个步骤流失率最高?产品经理支支吾吾,只能说回头加上埋点,过半个月再分析。之后,领导转向技术团队,问系统的峰值 TPS/QPS 分别是多少,99%的响应时间是多长,错误率是否低于 0.05%,哪个服务的响应时间最长?开发负责人也是一脸茫然。


案例二,另一个团队在办公室一面墙上安装了若干展示大屏,上面最下层显示的是各个服务器的 CPU/内存实时占用数据,还有网络带宽的利用率,网络延时,数据库的 CPU/IOPS/慢 SQL/吞吐量等指标;往上一层展示的是各个应用的 CPU/内存波动情况,还有 TPS、响应时间、JVM 垃圾回收、错误率等数据;在网上一层,有当天的 PV/UV 数据,各个页面的点击数,停留时长;在网上有展示交易数据,包括一定时间段内的总订单数、客单价、销量排名前 10 的商品、客户地域分布、复购率、退货率等运营指标,还有每日新增客户数,活跃客户数等等。


对比这两个团队的工作表现,假设我们单从上述现象出发,你觉得哪个团队表现得更加专业?哪个团队的工作更加细致?如果让你选择一个团队进行投资,你愿意投资哪一个团队?我想正常情况下,大部分投资人肯定会选择第二个团队,无他,源于他们对各项工作的充分掌握,因为有明镜般的掌控力,运营才能够有的放矢,知道推广哪些商品,知道广告的呈现;产品才能够知道下一步迭代应该优化哪基础交互,哪几个流程需要重新设计,减少用户心智负担;技术团队也更加清楚哪些服务的性能不达标,哪些服务需要加大资源投入;运维团队也能够更加确定该在哪些地方增加监控,指标该如何设置等等。


我想说到这里,大家对可观测性应该有一定的理解了。可观测性的本质在于对系统全方面运行和运营情况的及时感知,并指引各项工作更加科学合理地开展,避免凭感觉下结论,凭经验做判断,更避免资源浪费。

因此,可观测性是决策的基石,不是不重要,而是我们没有发现他的美妙之处。


可观测性不是随随便便就可以获得的,有些指标或许通过事后的监控或者直接从数据中提取可以获取,但是有些指标是需要在方案设计时进行考虑的,譬如系统的性能数据,譬如 PV/UV。因此,面向可观测性设计,应该成为一种常态和基本意识。


最后,实施可观测性应该避免落入面子工程,即只是放置几块大屏幕,彰显公司的门面。指标的设计需要与业务紧密贴合,指标之间具备联动性和互相印证性。


八、容错性

系统不是在真空中运行的,使用系统的人员或其他系统也无法保障 100%的准确无误,所以一款设计良好的系统,应该具备在各类不确定性甚至是充满不正当使用的前提下能够正常的运行,对正确的结果给予正确的回应,对错误地使用给出明确的错误提示,而系统自身仍然能够保持高度的稳定性,不因异常信息的输入而变得脆弱甚至失去提供服务的能力。


错误可能来自多方面。


首先,是基础设施层面的错误。这类错误几乎无法避免。CPU 可能会因为某些原因而高位运行,导致系统的线程被阻塞,进而导致超时发生;内存也可能因为运行高耗内存的应用而导致满负荷,出现程序内存无法分配而异常;如果说 CPU 和内存相对容易控制,通过限制每一个应用程序可使用的 CPU 和内存上限而加以约束,从而降低惊群现象,但是对于网络的抖动几乎是一个短期内没有很好的解决办法的普遍性难题。全球高科技企业非常多,但没有哪一家高科技企业可以彻底解决网络抖动问题,说到底网络问题是一个异常复杂的无法统一管理地受到物理材料约束的分布式问题。因此,对于系统而言,正面这些潜在的问题,并积极应对,也许对想方设法地杜绝来得更加明智,也更加具备可行性。


那么,如何化解这一层面的错误呢?冗余和重试是两个不错的选择。对于冗余,最直观的理解就是分布式部署,通过多个节点来对冲单一节点才能存在的问题。假设系统 A 的故障率是 0.05%,假设部署双节点,则理论上两个节点同时故障的概率约为 0.05%*0.05%,无疑下降显著。而重试怎可以解决依赖的其他系统出现错误时的自救。有些故障本是瞬间的,通过间隔片刻进行重试,可以极大解决这类问题。而对于无法自愈的故障,通过设置阶梯性的重试,也可以在有问题的系统被人力修复后系统自身也完成剩余的任务。


其次,来自使用方的错误。包括来自终端用户的操作错误和来自上游系统的调用错误。来自终端用户的错误包括输入数据不合法,或者没有按照规定的操作流程进行使用;来自上游系统的错误主要有参数不合法、频繁调用、重试不合理等异常情况。对于这一类错误,比较好的办法有检查、过滤和短时间封控制。对于参数不合法,输入错误,通过全面的检查,可以避免异常数据流入系统,从而污染系统数据,也妨碍正常流程的流转;对于大批量输入的数据,通过过滤掉不合格的数据,让其他正常数据得以正常被受理,也可以将影响范围进行隔离以降低不良影响;而对于上游系统没有按照合理的频次进行调用,通过封控即可以保护系统,避免资源被耗尽,还可以隔离恶意请求以为正常请求保留足够的处理空间。


最后,错误还可能来自系统内部。包括数据传输过大导致的内存溢出、多线程限制不合理导致资源耗尽、控制条件存在缺陷导致死循环等等。针对这一类问题,比较好的处理办法就是设置相应的规范,限制操作的范围,以达到隔离风险的目的。


总之,风险无处不在,错误也是伴随着任何系统共生。提升系统自身的容错性,面对错误也能够正常运行才是一个优秀系统该有的表现。


九、可恢复

故障总是无法避免的,而且一般故障总是会被解决,不管持续的时间是瞬间还是几个小时。但问题是当故障被排除后,遭遇故障的系统是否能够完好地恢复呢?也许我们会觉得这不是天经地义的吗,软件之所以是软件,正是因为他没有硬件的物理特性,不存在裂痕或者破洞这类的遗留问题?然而现实真的理所应当如此吗?我们举一个数字经济时代大家都很熟悉的场景,电商购物。假设客户 A 从商户 B 处选购一批特价中秋礼盒和烟酒商品,该批特价礼盒因为是特价版所以数量有限,而且价格非常实惠(平时 500 一盒,现在 350 一盒)。假设客户 A 在线支付的过程中,因为网络等原因,支付卡住了,过了很久才反应过来,最终支付成功了,但是因为过程较长,仅剩不多的商品已经被其他客户抢售一空了。而且支付过程中使用了代金券和因为金额超过一定阈值带来的折扣优惠(满 2000 打 9.5 折),而这些代金券只能一次使用无法退回二次使用。假设你是运维人员,遇到这样的案例,你该怎么办?因为商户的库存不足,所以必须要退款。但是退款又会导致总金额不足 2000,原本给予的优惠要给不要?如果不给,客户会投诉,因为是系统故障;如果给了,平台需要承担损失。另外,代金券怎么处理呢?因为是一次性的物品,无法重复使用。如果给客户补偿现金,则平台有需要承担损失,如果不补偿,则于理不合。遇到这样的困难局面,虽然最终在接受经济损失和忽略不精确的情况下可以解决,但是由于系统而言,却表现得差强人意。况且这里我们列举的只是一个比较简单的情况,如果设计到更多的人,更多的关联方,更复杂的情况,又该如何处理呢?


因为,要保证系统具备从故障中快速且顺畅地恢复过来,必须确保在遇到异常情况时,系统的逻辑是完整的,数据是一致的,并且这些情况必须在设计的考量范围之内,避免出现意料之外的情况。


合理地使用事务,确保强相关的数据一致性,是确保可恢复的重要措施之一。在很多场景下,数据是动态变化的,如果关联各方的数据,一部分成功处理,一部分失败,经过多轮业务交易之后,要想再通过技术手段保证数据恢复到完全一致的局面,则变得非常困难,甚至难以完成。


其次,应用底线思维,确保对异常情况有充分的认知、设计和应对机制。很多系统正常运行都是非常平顺的,但是一旦其中某些环境出现问题,后果会怎么样,谁也无法说得清楚,这将是一个巨大的风险。因为最怕的不是故障,而是故障后对破坏力的一无所知,以及所带来的被动局面。一个合格的设计方案,应该是尽可能避免出现未知情况,让一切纳入可控的框架内。


最后,设置合理可靠的备份机制,确保无可抵御性事故下的可恢复性。天灾人祸总是与人类命运息息相关。人类在天灾面前往往显得异常渺小和无助。一旦遭遇天灾,系统又该如何确保平稳地度过浩劫,或者在灾难之后及时得到重建恢复呢?合理的备份机制往往非常重要,譬如数据库备份、磁盘备份。我们不妨做一个大胆的猜想,假设某一个本地银行没有灾备机制,很不幸遭遇一场罕见的大地震,银行服务器所在的机房被摧毁一空。经过全社会的大力救援之后,城市逐渐恢复,受伤群众也得到了妥善的安置。似乎一切开始朝积极的方向发展了。可突然广播告知,当地半数居民的毕生积蓄存储的本地银行服务器全部损坏,所有数据无法恢复。这算不算二次地震?甚至有可能被地震伤及的群体更多。


十、可控性

从事资金往来业务的从业者一般对人民银行不定期地关闭转账通道进行系统维护的通知一般不会陌生。即使不是从事资金业务,其他业务的从业者,也会或多或少遇到下游供应商不管是因为故障意外停止服务还是遇到重大系统升级不得不短暂中断服务提供。作为技术人员,当你面临这样不可控局面时,你该如何?是初步判断这类事情发生的频率不会跳高,从而默认接受这类事情的发生呢?还是说系统设计之初就有考虑到这类问题,并提前做了控制端点,可以方便系统运维人员通过控制端点规避这类问题的影响。


无论是出于灵活应对突发的事故,还是方便运营人员日常使用,一个可控制的系统都是深得人心的,毕竟没有人希望任何大事小事都需要开发写代码、测试验证再上线这样一个缓慢且风险巨大的流程。更何况如果是产品化且出售给了客户,这样的流程更加不存在了。


我们以汽车为例。汽车作为重资产的工业产品,必然无法做到按照每一个客户的需求对核心部件和布局进行柔性生产和定制制造,但是不同的用户又存在不同的用车习惯。譬如有的用户对经济性要求很高,很希望汽车自动启停功能,因为可以节约燃料;有的客户要求顺畅的乘坐体验,不希望自动启停带来的顿挫感。如果汽车的设计师,你会如何设计呢?毫无疑问提供开关是最简单的解决办法,把选择控制权交给用户,如果你没有这样的开关,面对不同偏好的客户,不管你默认是启动该功能还是暂停该功能,都会让一部分用户失望。其次,汽车是需要定期保养维护的工业制品,假设生产厂家没有维修保养模式,会不会导致很多部件无法维修呢?再次,维修工程师要对汽车的胎压进行检测和设置,如果没有暴露相关的接口,维修工工程师该如何操控呢?


因为可控制性对于一款成熟的产品,适应不同需求的用户,以及应对不同的场景都非常必要。


常见的实现可控制性的方式主要有以下几点。


其一,通过开关或配置项,实现功能控制。有了开关或配置项,不同群体既可以根据自身的实际需要进行选择,提升产品针对不同用户的需求匹配度,也扩大产品的服务范围,增强竞争力。


其二,预留控制接口,实现对内部处理逻辑的操纵。很多产品除了提供面向用户正常操作的功能之外,为了方便后续的维护和升级,也都会预留运维控制接口,只是这些接口往往对普通用户默认是不可见的,只有了解内情的人员才能够唤醒或开启这类功能。


可控制性就好比系在风筝上的线。因为有了线,即使风筝飞得再高,放风筝的人也内心很淡定,一旦遇到狂风或暴雨,因为有了线,放风筝的人便可以快速回收,避免被风雨裹挟远去。假设没有线,遇到风雨,放风筝的人即使再着急也无能为力,是不是像极了某些系统的运维人员事故面前手足无措干着急的狼狈样子?

发布于: 刚刚阅读数: 4
用户头像

凌晞

关注

一枝有思想有深度的芦苇 2011-02-27 加入

一名有文化素养的IT从业者

评论

发布
暂无评论
企业架构设计原则之品质均衡性(二)_企业架构_凌晞_InfoQ写作社区