系统架构对话(五):设计已经做完了,怎么知道它哪里会出问题?
系统架构对话第 5 篇
前四篇都是从质量目标出发找手段:要性能,就看缓冲、并发和调度;要可用性,就看检测和恢复。可真实项目里,很多决定早就做完了。这时更常见的问题是反过来的:这些已经做了的决定,对系统意味着什么,哪里可能出问题?
这就是架构评估要回答的事。这一篇仍用那套五路采集系统,素材全是前面几篇已经出现过的决定。
案例设定:一个主界面进程加五个采集进程,一路一个进程;每路输入约 26 MB/s;采集进程每秒上报一次状态,主界面进程连续 3 次收不到就判定出事并重启它;原始包直接存盘,离线后处理程序负责帧对齐和数据转换。
一个决定,几个属性
问:把五路拆成一路一个进程,哪些质量属性变好了,哪些变差了?
答:我的第一反应是“可靠性提高了,复杂度也提高了”。前半句方向对:一路崩溃不再拖垮其他四路,主界面进程还会自动重启它,更贴切的说法是可用性变好。还漏了性能,拆进程的初衷本来就是让五路不再挤在一个进程里抢线程、一起被同一次回收停住。
后半句的问题在“复杂度”。它不是质量属性,没法和变好的那几项放在一起比。评估做不下去,往往就卡在这种说法上。
问:那换个问法:拆开以后,开发或测试时哪一件具体的事更费劲了?
答:多了一套进程间通信。“连续 3 次收不到上报就重启”是跨进程的行为,得手动杀进程才测得到,这是可测试性下降;采集进程想多报一个字段,两边程序和通信约定都要改,版本还得对上,这是可修改性下降。
合起来看,拆进程这一个决定,把性能、可用性往上拉,把可测试性、可修改性往下拉。一个决定同时牵动多个质量属性、而且方向相反,这种点叫权衡点。
说代价时,别停在“复杂了”。问一句“哪件事变费劲了”,再把那件事翻译成质量属性。
一个参数,一个属性
问:回读缓冲从 64 MB 改成 8 MB,最先受影响的是什么?
答:性能。第二篇算过,缓冲区买到的是时间:落盘偶尔慢一下,数据还在按每秒约 26 MB 进来,全靠缓冲区接住。缓冲越小,能扛的停顿越短,丢帧率就上去了。
丢帧率这个目标对“缓冲区大小”这个参数很敏感,所以它是性能的一个敏感点。敏感点本身不分好坏,它提醒的是:这里不能随手改,改了要重新验证对应的目标。
问:反过来调大到 1 GB,除了性能,还有什么会变差吗?
答:要看约束。内存富余、以后也不加路,那基本只影响性能;内存总量固定、以后还要多接几路,那每路占得越多,能接的路数就越少,可伸缩性变差了。
| 缓冲区大小,在什么约束下 | 牵动的质量属性 | 它算什么 |
|---|---|---|
| 内存富余,路数不再增加 | 基本只有性能 | 敏感点 |
| 内存固定,以后还要多接 | 性能变好,可伸缩性变差 | 权衡点 |
同一个参数是敏感点还是权衡点,取决于系统处在什么约束下。评估时把约束一起写下来,结论才站得住。
可能落空的,可以接受的
问:数据测完以后才拷到服务器归档。在那之前,原始数据只在采集电脑上,而这台电脑上的软件没有登录,谁都能操作。这段时间可能发生什么?
答:磁盘坏了,或者有人误删。两种情况分属不同的质量属性:误删是安全性(完整性)的问题,少了授权这一步;磁盘损坏是可靠性的问题,拷走之前只有一份。
这就是风险点:一个架构决定,可能让某个高优先级的质量目标落空。这里有两件事值得留意。第一,没做的决定也算。“不做访问控制”“拷走前只存一份”都不是写出来的代码,但都是架构决定,风险恰恰出在这里。第二,风险点带着判断,而敏感点、权衡点只说“这里牵动了哪些属性”。
问:采集进程崩溃时会丢几秒数据,也没有给每一路做主动冗余。为什么认为这不是问题?
答:要用的数据可以重新采;丢几帧对整份测试报告影响很小。再加上第一篇定下的口径:丢帧率低于 1% 指正常采集期间,不含崩溃造成的中断。
这是非风险点。它的关键在于总是带着前提,可以写成这样一句:
假设崩溃后能自动重启,丢失的几秒数据可以重采或对报告影响很小,则不给每一路做主动冗余是可以接受的。
前提一变,非风险就会变成风险。比如道路测试碰上一个很难再遇到的路况,偏偏这几秒丢了,又没法重采。所以前提要和结论一起记下来。
问:评估结论交给项目经理,哪一类最需要拿去安排人和时间?
答:风险点。这也是结论要分成四类的原因:交出去以后,用法各不相同。
| 结论 | 交出去以后怎么用 |
|---|---|
| 风险点 | 进行动计划:改设计,或者想办法降低风险 |
| 非风险点 | 不用花钱,但前提要记下来,前提变了要重新评估 |
| 敏感点 | 提醒开发和运维:这个参数改了,要验证对应的目标 |
| 权衡点 | 请相关的人一起拍板:往哪边倾斜,是业务决定 |
一句结论怎么认
问:“调整业务数据的编码方式,会同时影响系统的性能和安全性。”这算风险点吧?毕竟要改设计。
答:我第一次也是这么判断的,但“要改”不是风险的标志。敏感点和权衡点本来就是在说“改了这个特性,质量属性会跟着变”。这句话没说哪个目标会落空,只说编码方式同时牵动了两个属性,所以是权衡点。
与其凭字眼猜,不如按固定的顺序看:
试着按这个顺序判断三句话
① 把心跳上报间隔从 1 秒缩短到 0.1 秒,能更快发现采集进程故障,但进程间通信的开销也会增加。② 系统的日志格式至今没有统一规范,后续可能导致故障定位困难,影响可维护性。③ 数据库连接池的大小,决定了高峰期请求的响应时间。
① 权衡点:同样带着“改动”,但它牵动可用性(发现更快)和性能(开销更大)两个属性。② 风险点:“至今没有”“可能导致”。③ 敏感点:只牵动性能。
拿场景到架构上走一遍
问:如果评审的办法是发一张检查表,请几位资深同事按经验逐项打分,最大的弱点是什么?
答:大家拿到的是同一张表,可每一项“好不好”,仍由各人凭经验判断,结论很大程度上取决于打分人。这种办法便宜,能把大家的经验用起来,但很难回答“凭什么这么判断”。
另一类做法是拿具体场景到架构上走一遍,看架构到底怎样应对。
问:场景是“某一路采集进程崩溃,要尽快恢复采集”。从崩溃那一刻起,依次会发生什么?
答:我先写的是“无法采集,系统检测到崩溃,系统主动恢复”。顺序没错,但三步都只说了“应该发生什么”,没说“靠什么发生”。这种答案,打检查表的同事也会给,评审拿它判断不了好坏。追问“哪个进程、靠什么发现”,才落到了实处:主界面进程,靠心跳。
走完以后,场景的度量就能算出来:这一路大约缺 3 + N 秒的数据,可以直接和需求对比。更有用的是,走的过程中会顺带冒出评估结论:心跳间隔和“连续 3 次”的门限是可用性的敏感点,间隔缩短又会牵动性能;整个恢复都靠主界面进程,它自己出事、还没恢复的那段时间里,采集进程再崩溃由谁来重启?这一点还需要确认,先记为待确认的风险点。
场景走查的每一步,都要回答“哪个构件、靠什么机制、用多少时间”。只写目标,就退回了凭感觉打分。
修改场景要走完整条链路
问:刚才是运行时的场景。假设以后换一种采集卡,哪些构件要改?
答:我先想到的是“新加一个采集类,其他基本不用改”。厂家相关的知识确实集中在采集类里,这一处对。
问:可是落盘存的是原始包,带着这家采集卡自己的包头格式。离线的帧对齐和转换程序还能直接用吗?
答:不能。修改场景要沿整条链路走:在线采集、落盘格式、离线后处理,凡是被牵连到的都要算。再加上主进程里绑定采集卡的那段逻辑,换卡一共要改三处。第四篇讨论“协议差异放在哪里”时,遇到的正是这条链路。
按这种方式逐个检查修改场景,可以把场景分成两种:现有架构不用改就支持的,比如运行中动态增减一路;要改架构才支持的,比如换卡,并列出要改的构件。接着再看几个要改架构的场景,会不会撞在同一个构件上:
| 修改场景 | 要改的构件 |
|---|---|
| 换一种采集卡 | 采集类、主进程的绑定逻辑、离线后处理程序 |
| 改落盘格式 | 采集进程的写入、离线后处理程序 |
两个场景都撞在后处理程序上,因为它既要认识厂家的包格式,又要负责格式转换。撞在一起的场景越多,说明这个构件管的事越杂,后面也越难改。把协议描述作为后处理程序的输入,作用就是把这两个场景拆开。
这一套做法就是 SAAM 的核心。它是较早成形的架构分析方法,主要用来看可修改性:开发修改场景,描述架构,逐个评估场景,再看场景之间的交互,最后作出总体评价。场景交互是它最有特色的一步。
场景太多,先走哪些
问:这个系统里性能、可用性、安全性、可修改性都要看,场景能列出几十个。评审只有半天,下面五个只能先走两个,挑哪两个?
① 某一路采集进程崩溃 ② 主界面进程崩溃 ③ 换一种采集卡 ④ 测完还没拷走的数据被人误删 ⑤ 主界面换一套配色
答:我挑了 ① 和 ②,理由是“它们影响到系统核心”。这用的是重要性,是对的标准之一,但还缺一个:让架构满足这个场景有多难。
ATAM 用效用树处理这个问题。从“效用”出发,往下分出质量属性、属性分类,叶子是具体场景。修剪掉配色这类无关紧要的场景,再给每个叶子标两个档位:重要性、实现难度,各分 H、M、L。
标完以后出现了一个反差:挑场景时我没挑 ④,可单独问它的重要性,我又给了 H。最怕丢的本来就是原始数据。只凭直觉挑,人容易盯着自己熟悉的那一两类属性;效用树把几类属性并排摆出来,漏掉的就显出来了。
(H, M)、(H, H) 这类场景重要又不好做,风险多半藏在里面,要花时间细走。④ 是 (H, L):重要,但处理起来不难,很快就能定下办法。
回头看,这一篇前面做的事,正是 ATAM 的主线:收集场景并排出优先级,把重要场景放到架构上走,从中标出敏感点和权衡点,找出风险和非风险。它和 SAAM 的区别在于不只盯一个属性,而是在多个质量属性之间权衡。完整的步骤可以读 SEI 的 ATAM 技术报告。
先花钱解决哪个
问:误删这个风险点,有两个方案都能降低它:甲,给采集电脑上的软件加登录和权限;乙,每段数据录完,自动再复制一份到另一块硬盘。按什么选?
答:我说的是“成本和复杂度,以及风险发生的概率”。成本和概率都对,“复杂度”其实也属于成本。还缺一个关键维度:收益,也就是每个方案到底能挡住多少损失。两个方案挡住的东西并不一样:
| 方案 | 挡得住误删 | 挡得住磁盘损坏 | 牵动的其他属性 |
|---|---|---|---|
| 甲 登录和权限 | 能 | 不能 | 易用性:采集时多一步登录 |
| 乙 自动再存一份 | 大部分能,除非两份都被删 | 能 | 性能:五路合计约 130 MB/s,写入量翻倍 |
所以不能只看哪个便宜,要看每花一份成本,能换回多少收益。CBAM 做的就是这笔账:它接着 ATAM 的结果往下走,估算各个架构策略的成本和收益,按投资回报排序。ATAM 告诉你哪里有风险,CBAM 帮你决定先花钱解决哪个。
请谁来评
问:评审这套系统,除了开发人员,还应该请谁?
答:我列了架构师、设计人员、测试人员、需求人员。这些人都站在造系统的一方,还缺用系统和维护系统的人:
| 谁 | 在这个系统里 | 会带来什么场景 |
|---|---|---|
| 最终用户 | 开车采数的测试人员 | 开车时看不了屏幕,要声音告警;某段断了要能重跑 |
| 用数据的人 | 拿数据出报告的人 | 丢多少帧会影响结论;数据要保存多久 |
| 维护的人 | 管采集电脑和归档服务器的人 | 磁盘满了怎么办;谁有权删数据 |
| 设备专家 | 熟悉采集卡的人 | 下一代采集卡的接口会怎么变 |
请哪些人,决定了能收集到哪些场景。挑场景时差点漏掉 ④、列评审人员时只想到开发一方,其实是同一个盲点:只从造系统的角度看。
问一个场景重不重要之前,先问一句:它是谁会提出来的?
三种方法放在一起
这一篇用的素材,全是前四篇已经做过的决定。评估并没有引入新技术,它做的是把这些决定重新摆出来,逐个问清楚:牵动了哪些属性,在什么前提下可以接受,哪里可能落空,以及先处理哪个。
试着在自己的系统里找一遍
各找一个敏感点、权衡点、风险点和非风险点,非风险点写出“假设……,则……是可以接受的”的完整句子。再挑一个重要的运行时场景,按“步骤、构件、机制、时间”走一遍,看能不能算出度量,路上又冒出了哪些点。最后列出会提出场景的人,看看有没有只站在开发一方。
下一篇会把 ATAM 用到一个完整的案例上:从一组零散的系统描述里整理出效用树,再从中找出风险、敏感点和权衡点。