软件架构基础课

第20章 分析架构风险

2021-03-01  本文已影响0人  城里的月光_欧阳

每种架构都有与之相关的风险,无论是涉及可用性、可扩展性还是数据完整性的风险。架构风险分析是架构的关键活动之一。通过不断分析风险,架构师可以解决架构中的缺陷,并采取纠正措施来降低风险。在本章中,我们将介绍一些关键技术和实践,这些技术和实践可用于确认风险、创建风险评估,以及通过一项名为“风险风暴”的活动来识别风险。

风险矩阵

评估架构风险时出现的第一个问题是确定风险应归类为低、中还是高。在这种归类中通常会引入过多的主观性,从而造成对架构中哪些部分是真正的高风险还是中等风险的混淆。幸运的是,架构师可以利用一个风险矩阵来帮助降低主观性的水平,并量化与架构的特定领域相关的风险。

架构风险矩阵(如图20-1所示)使用两个维度来量化风险:风险的总体影响和风险发生的可能性。每个维度都有一个低(1)、中(2)和高(3)等级。这些数字在矩阵的每个网格内相乘,提供表示该风险的客观数字。数字1和2被认为是低风险(绿色),数字3和4被认为是中等风险(黄色),数字6到9被认为是高风险(红色)。

图20-1.确定架构风险的矩阵

为了了解如何使用风险矩阵,假设需要考虑应用中使用的主中央数据库的可用性。首先,考虑影响维度:如果数据库关闭或变得不可用,总体影响是什么?在这里,架构师可能会认为风险很高,将该风险设为3(中等)、6(高)或9(高)。然而,在应用第二个维度(风险发生的可能性)之后,架构师意识到数据库位于集群配置中的高可用服务器上,因此数据库变得不可用的可能性很低。因此,高影响和低可能性之间的交叉点给出的总体风险评级为3(中等风险)。

提示

当利用风险矩阵来确定风险时,首先考虑影响维度,其次考虑可能性维度。

风险评估

上一节中描述的风险矩阵可用于构建所谓的风险评估。风险评估是关于某种上下文和有意义的评估标准的架构总体风险的总结报告。

风险评估的形式可以各式各样,但一般来说,它们包含基于应用的服务或领域的某些评估标准的风险(从风险矩阵中量化)。基本的风险评估报告格式如图20-2所示,其中浅灰色(1-2)表示低风险,中灰色(3-4)表示中等风险,深灰色(6-9)表示高风险。通常这些颜色编码为绿色(低)、黄色(中)和红色(高),但采用阴影对于黑白渲染和色盲非常有用。

图20-2. 标准风险评估示例

风险矩阵中的量化风险可以通过风险标准以及服务或领域来累加。例如,请注意,在图20-2中,数据完整性的累加风险是最高的风险区域,总共是17,而可用性的累积风险只有10(风险最小)。每个领域的相关风险也可以通过例子中的风险评估来确定。在这里,客户注册服务的风险最高,而订单履行服务的风险最低。可以跟踪这些相关数字,以证明特定风险类别或领域内风险的改善或降低。

尽管图20-2中的风险评估示例包含了所有的风险分析结果,但很少会这样呈现。过滤对于在给定上下文中直观地指示特定消息是必不可少的。例如,假设一个架构师正在开会,目的是展示系统中高风险的区域。除了展示图20-2所示的风险评估,过滤可以用于只显示高风险区域(如图20-3所示),提高整体信噪比,并呈现系统状态的清晰图像(好或坏)。

图20-3. 过滤风险评估仅显示高风险

图20-2的另一个问题是,该评估报告仅显示了一个时间快照;它并不能显示情况是在好转还是在恶化。换句话说,图20-2没有显示风险的趋势。呈现风险方向在某种程度上是一个问题。如果用向上或向下箭头来表示方向,向上箭头是什么意思?情况是好转还是恶化?我们花了数年时间询问人们向上箭头是否意味着事情变得更好或更糟,近50%的人说向上箭头意味着事情逐渐变得更糟,而近50%的人说向上箭头表示事情正在变得更好。左右箭头也是如此。因此,当使用箭头指示方向时,必须使用关键字。然而,我们也发现这也不起作用。一旦用户滚动到关键字之外,疑惑就会再次发生。

我们通常在风险评级旁边使用加号(+)和减号(-)的通用方向符号来表示方向,如图20-4所示。请注意,在图20-4中,尽管客户注册服务的性能风险为中等(4),但方向为负号(红色),表明它正在逐渐恶化并走向高风险。另一方面,请注意目录签出服务的可扩展性风险很高(6),带有一个加号(绿色),表明它正在改善。没有加号或减号的风险评级表明风险是稳定的,没有好转也没有恶化。

图20-4.用正负号表示风险趋势方向

有时,甚至加号和减号也会让一些人感到迷惑。指示方向的另一个技巧是利用箭头和它所趋向的风险评级数字。如图20-5所示,这种技术不需要关键字,因为方向很清楚。此外,颜色的使用(红色箭头表示恶化,绿色箭头表示改善)使风险的趋势方向更加清晰。

图20-5.用箭头和数字显示风险趋势方向

通过使用本书前面描述的适应性函数的连续测量,可以确定风险的趋势方向。通过客观分析每个风险标准,可以观察到趋势走向,从而为每个风险标准提供方向。

风险风暴

没有一个架构师能够单枪匹马地确定系统的总体风险。原因有两个方面。首先,一个架构师可能会错过或忽略一个风险区域,很少有架构师对系统的每个部分都有充分的了解。这就是风险风暴可以提供帮助的地方。

风险风暴是一种协作活动,用于确定特定维度内的架构风险。常见维度(风险领域)包括未经验证的技术、性能、可扩展性、可用性(包括可传递的依赖关系)、数据丢失、单点故障和安全性。尽管大多数风险风暴涉及到多个架构师,但明智的做法是也把高级开发人员和技术负责人包含进来。他们不仅可以提供架构风险的实施层面的观点,而且让开发人员参与进来有助于他们更好地理解架构。

风险风暴的工作既包括个人部分,也包括协作部分。在个人的部分中,所有参与者使用上一节中描述的风险矩阵将风险单独(无需协作)分配给架构的各个区域。风险风暴的这一非协作部分非常重要,这样参与者就不会影响或直接将注意力从架构的特定区域引开。在风险风暴的协作部分,所有参与者共同努力,就风险区域达成共识,讨论风险,并形成减轻风险的解决方案。

架构图用于风险风暴工作的两个部分。对于整体风险评估,通常使用综合架构图,而应用程序特定区域内的风险风暴将使用上下文架构图。进行风险应对工作的架构师有责任确保这些图表是最新的,并可供所有参与者使用。

图20-6显示了我们将用于说明风险风暴过程的示例架构。在这个架构中,弹性负载平衡器在每个都包含web服务器(Nginx)和应用服务的EC2实例之前。应用服务调用MySQL数据库、Redis缓存和MongoDB数据库进行日志记录。他们还调用推送扩展服务器。扩展服务器依次与MySQL数据库、Redis缓存和MongoDB日志记录工具进行连接。

图20-6.风险风暴示例架构图

风险风暴分为三个主要活动:

1、识别风险

2、达成共识

3、减轻风险

识别风险始终是一种个人的、非协作的活动,而达成共识和缓解风险则始终是协作的,所有参与者都在同一个房间(至少是虚拟的)一起工作。以下各节将详细讨论这些主要活动。

识别风险

风险风暴的识别风险活动涉及每个参与者分别识别架构内的风险区域。以下步骤描述了风险风暴的识别风险工作:

1、进行风险风暴的架构师在协作部分工作开始前一到两天向所有参与者发出邀请。邀请包含架构图(或找到它的位置)、风险风暴维度(针对特定风险风暴工作分析的风险区域)、风险风暴协作部分的日期和地点。

2、使用本章第一节中描述的风险矩阵,参与者分别分析架构,并将风险分为低(1-2)、中(3-4)或高(6-9)。

3、参与者准备带有相应颜色(绿色、黄色和红色)的小便笺,并记下相应的风险编号(见风险矩阵)。

大多数风险风暴工作只涉及分析一个特定维度(如性能),但由于人员空闲或时间安排问题,有时可能会在单个风险风暴工作中分析多个维度(如性能、可扩展性和数据丢失)。当在一次风险风暴中分析多个维度时,参与者将维度写在便笺上的风险编号旁边,以便每个人都知道具体的维度。例如,假设三个参与者在中央数据库中发现了风险。三个参与者都认为风险很高(6),但一个参与者发现了可用性方面的风险,而两个参与者发现了性能方面的风险。这两个维度将分别讨论。

提示

只要有可能,将风险风暴的努力限制在一个维度上。这使参与者能够将注意力集中到该特定维度上,并避免对为架构的同一区域确定的多个风险区域的混淆。

达成共识

风险风暴工作中的达成共识活动是高度协作的,目的是在所有参与者之间就架构内的风险达成共识。当一个大的,印刷版的架构图就绪并张贴在墙上时,这个活动是最有效的。作为印刷版本替代,电子版本可以显示在大屏幕上。

到达风险风暴会议后,参与者开始在架构图上他们各自发现风险的区域放置他们的便利贴记录。如果使用电子版本,组织风险风暴会议的架构师会询问每个参与者,并以电子方式将风险放在架构图中识别风险的区域上(见图20-7)。

图20-7.风险区域的初步识别

一旦所有的便利贴都准备好了,风险风暴的协作部分就可以开始了。这项风险风暴活动的目标是作为一个团队分析风险领域,并就风险鉴定达成共识。请注意,架构中确定了几个风险区域,如图20-7所示:

1、两名参与者分别将弹性负载均衡器确定为中等风险(3),而一名参与者将其确定为高风险(6)。

2、一位参与者将推送扩展服务器单独标识为高风险(9)。

3、三位参与者分别将MySQL数据库标识为中等风险(3)。

4、一位参与者将Redis缓存单独标识为高风险(9)。

5、三名参与者认为MongoDB日志记录为低风险(2)。

6、架构的所有其他区域均未被视为具有任何风险,因此架构的任何其他区域均无便利贴记录。

上面列表中的第3项和第5项不需要在本活动中进一步讨论,因为所有参与者都同意风险的级别和资格。但是,请注意,列表中的第1项存在意见分歧,第2项和第4项只有一个参与者确定了风险。这些项目需要在活动期间进行讨论。

列表中的第1项显示,两名参与者分别将弹性负载均衡器识别为中等风险(3),而一名参与者将其识别为高风险(6)。在这种情况下,其他两个参与者问第三个参与者为什么他认为风险很高。假设第三个参与者说,他们将风险识别为高风险,因为如果弹性负载均衡器发生故障,则无法访问整个系统。虽然这是真的,事实上确实使整体影响评级变高,其他两名参与者说服第三名参与者,这种情况发生的风险很低。经过多次讨论,第三位参与者同意了,将风险水平降低到中等(3)。然而,第一个和第二个参与者可能没有像第三个参与者那样在弹性负载均衡器中看到风险的特定方面,因此需要在这个风险风暴活动中进行协作。

举个例子,考虑前面列表中的第2项,其中一个参与者将推送扩展服务器单独标识为高风险(9),而没有其他参与者将其标识为任何风险。在这种情况下,所有其他参与者都会询问识别出风险的参与者为什么将其评为高风险。那个参与者接着说,他们有过推送扩展服务器在高负载下持续宕机的糟糕经历,这个是特定架构所具有的问题。这个例子展示了风险风暴的价值,如果没有这个参与者的介入,没有人会看到高风险(当然,在投入生产之前!)。

清单中的第4项是一个有趣的例子。一位参与者将Redis缓存识别为高风险(9),而没有其他参与者将该缓存视为架构中的任何风险。其他参与者询问该区域为高风险的原因是什么,那个参与者回答说,“什么是Redis缓存?”在这种情况下,参与者不知道Redis是什么,因此该区域的风险很高。

提示

对于未经证实或未知的技术,始终指定最高风险评级(9),因为风险矩阵不能用于此维度。

清单中第4项的例子说明了为什么让开发人员参加风险风暴会议是明智的(而且是重要的)。开发人员不仅可以更多地了解架构,而且一个参与者(在本例中是团队中的开发人员)不知道给定的技术这一事实为架构师提供了关于总体风险的有价值的信息。

这一过程一直持续到所有参与者就确定的风险领域达成一致为止。一旦所有的便利贴记录都被合并,这个活动就结束了,下一个活动就可以开始了。该活动的最终结果如图20-8所示。

图20-8.风险区域达成共识

减轻风险

一旦所有参与者就架构的风险区域的量化达成一致,最后也是最重要的活动就是减轻风险。减轻架构中的风险通常涉及对架构的某些区域进行更改或增强,否则这些区域可能被认为是完美的。

这项活动通常也是协作性的,寻求减少或消除第一项活动中确定的风险的方法。在某些情况下,可能需要根据风险识别对原始架构进行完全更改,而其他情况可能是直接的架构重构,例如添加一个用于背压的队列以减少吞吐量瓶颈问题。

不管架构中需要做什么更改,这项活动通常都会产生额外的成本。因此,关键利益相关者通常决定成本是否大于风险。例如,假设通过一个风险风暴会议,中央数据库在总体系统可用性方面被确定为中等风险(4)。在这种情况下,与会者一致认为,将单个数据库拆分为单独的物理数据库进行集群,将减轻这种风险。然而,虽然风险将大大降低,但这一解决方案将花费20000美元。然后,架构师将与关键业务干系人举行一次会议,讨论这项利益权衡关系。在这次协商中,业务负责人认为价格太高,投入成本没有超过减轻风险所获得的好处。架构师并没有放弃,而是提出了一种不同的方法——跳过集群并将数据库分成两部分怎么样?在这种情况下,成本降低到8000美元,同时仍然减轻了大部分风险。在这种情况下,利益相关者同意了该解决方案。

前面的场景显示了风险风暴不仅会对整个架构产生影响,还会对架构师和业务涉众之间的协商产生影响。风险风暴与本章开头描述的风险评估相结合,为识别和跟踪风险、改进架构和处理关键利益相关者之间的协商提供了一个极好的工具。

敏捷故事风险分析

风险风暴可以用于软件开发的其他方面,而不仅仅是架构上。例如,在故事梳理期间,我们利用风险风暴来确定给定敏捷迭代中用户故事完成的总体风险(以及该迭代的总体风险评估)。使用风险矩阵,用户故事风险可以通过第一个维度(如果故事没有在迭代中完成的总体影响)和第二个维度(故事没有完成的可能性)来识别。通过对故事使用与架构相同的风险矩阵,团队可以识别高风险的故事,仔细跟踪这些故事,并对它们进行优先级排序。

风险风暴示例

为了说明风险风暴的威力以及它如何改进系统的整体架构,请考虑一个呼叫中心系统的示例,以支持护士就各种健康状况向患者提供建议。此类系统的需求如下:

- 该系统将使用第三方诊断引擎,提供问题并指导护士或患者有关他们的医疗问题。

- 患者可以使用呼叫中心呼叫护士,也可以选择使用自助服务网站绕过护士而直接访问诊断引擎。

- 该系统必须支持全国250名护士和全国数十万名自助病人并发访问。

- 护士可以通过病历交换访问患者的病历,但患者不能访问自己的病历。

- 对于医疗记录,系统必须符合HIPAA规定。这意味着,除了护士以外,任何人都不能查阅病历。

- 在感冒和流感季节爆发和大面积感染的情况需要在系统中解决。

- 呼叫护士的路由是基于护士的档案资料(如双语需求)。

- 第三方诊断引擎每秒可以处理大约500个请求。

系统架构师创建了如图20-9所示的高层次的架构。在这个架构中,有三个独立的基于web的用户界面:一个用于自助服务,一个用于护士接听电话,另一个用于管理人员添加和维护护士档案信息和配置设置。系统的呼叫中心部分包括一个接收呼叫的呼叫接受器和一个呼叫路由器,呼叫路由器根据其配置文件将呼叫路由到下一个有空的护士(注意呼叫路由器如何访问中央数据库以获取护士档案信息)。此架构的中心是诊断系统API网关,它执行安全检查并将请求定向到适当的后端服务。

图20-9.护士诊断系统的高层次架构实例

该系统有四个主要服务:病例管理服务、护士档案管理服务、病历交换接口和外部第三方诊断引擎。除了外部系统和呼叫中心服务的专有协议外,所有通信都使用REST。

架构师已经多次审核了这个架构,并相信它已经准备好实现了。作为自我评估,研究图20-9中的需求和架构图,并尝试确定该架构中可用性、弹性和安全性方面的风险级别。在确定风险级别之后,需要再确定在架构中进行哪些更改来减轻风险。下面的部分包含可以用作对比的场景。

可用性

在第一次风险风暴演习中,架构师选择首先关注可用性,因为系统可用性对于该系统的成功至关重要。在风险风暴识别和协作活动之后,参与者利用风险矩阵提出了以下风险区域(如图20-10所示):

- 使用中央数据库被确定为高风险(6),因为其影响范围为高(3)和发生可能性为中等(2)。

- 由于影响范围为高(3)和发生的可能性为未知(3),诊断引擎可用性被确定为高风险(9)。

- 医疗记录交换可用性被确定为低风险(2),因为它不是系统运行所必需的组件。

- 由于每个服务有多个实例和API网关集群化,系统的其他部分不被视为具有可用性风险。

图20-10.可用性风险区域

在风险风暴环节中,所有参与者都同意,如果数据库宕机了,护士可以手动写下病例笔记,但是如果数据库不可用,呼叫路由器就不能工作。为了降低数据库风险,参与者选择将单个物理数据库拆分为两个独立的数据库:一个包含护士档案信息的集群数据库和一个用于病例记录的单实例数据库。这种架构的更改不仅解决了对数据库可用性的担忧,而且有助于从管理员访问中保护病例记录。另一种减轻这种风险的方法是在呼叫路由器中缓存护士档案信息。然而,由于呼叫路由器的实现是未知的,而且可能是第三方产品,参与者采用了数据库方案。

由于缺乏对这些系统的控制,减轻外部系统(诊断引擎和病历交换)可用性的风险更难于管理。减轻这种可用性风险的一种方法是研究是否为这些系统中的每一个都发布服务级别协议(SLA)或服务级别目标(SLO)。SLA通常是合同协议和具有法律约束力,而SLO通常不具有法律约束力。根据研究,架构师发现诊断引擎的SLA保证99.99%的可用性(即每年52.60分钟的停机时间),医疗记录交换保证99.9%的可用性(即每年8.77小时的停机时间)。基于相对风险,这些信息足以消除已识别的风险。

图20-11说明了风险风暴会议后架构的相应变化。注意,现在使用了两个数据库,SLA也发布在架构图上。

图20-11.架构变更以解决可用性风险

可伸缩性

在第二个风险风暴练习中,架构师选择关注用户负载的弹性峰值(也称为可变可伸缩性)。虽然只有250名护士(为大多数服务提供自动调节器),但系统的自助服务部分可以访问诊断引擎和护士,这大大增加了对诊断接口的请求数量。参与者担心流感爆发和流感季节,届时系统的预期负荷将显著增加。

在风险风暴会议期间,所有参与者都将诊断引擎界面确定为高风险(9)。在每秒只有500个请求的情况下,参与者计算出诊断引擎接口无法跟上预期的吞吐量,特别是在当前使用REST作为接口协议的架构下。减轻此风险的一种方法是利用API网关和诊断引擎接口之间的异步队列(消息传递),以便支持对诊断引擎的调用时提供背压点。虽然这是一个很好的做法,但仍然不能降低风险,因为护士(以及自助服务患者)等待诊断引擎响应的时间太长,而且这些请求可能会超时。利用所谓的救护车模式将使护士获得比自助服务更高的优先级。因此需要两个消息通道。虽然这种技术有助于降低风险,但它仍然不能解决等待时间问题。参与者决定,除了提供背压的消息队列技术之外,缓存与爆发相关的特定诊断问题将使爆发和流感调用不再需要到达诊断引擎接口。

相应的架构变更如图20-12所示。请注意,除了两个队列通道(一个用于护士,一个用于自助服务患者)之外,还有一个新的服务,名为Diagnostics Explosion Cache Server,用于处理与特定爆发或流感相关问题的所有请求。有了这个架构,限制因素就消除了(对诊断引擎的调用),从而允许成千上万的并发请求。如果没有风险风暴的努力,这种风险可能无法确定,直到爆发或流感季节发生。

图20-12.架构变更以解决可伸缩性风险

安全性

受前两个风险风暴工作的结果和成功的鼓舞,架构师决定就系统中必须支持的另一个重要架构特性举行最后的风险风暴会议,以确保其成功,就是安全性。由于HIPAA法规要求,通过病历交换接口访问病历必须是安全的,仅允许护士在需要时访问病历。由于API网关中的安全检查(身份验证和授权),架构师认为这并不是问题,但很好奇参与者是否发现了任何其他安全风险元素。

在风险风暴期间,参与者都将诊断系统API网关确定为高安全风险(6)。这一高评级的理由是管理人员或自助服务患者访问医疗记录的高影响(3)与中等发生可能性(2)相结合。由于对每个API调用进行了安全检查,因此发生风险的可能性没有被评为高,但仍然被评为中等,因为所有调用(自助服务、管理员和护士)都要通过相同的API网关。仅将风险评级为低(2)的架构师在风险风暴共识活动期间,他被说服实际风险很高,需要进行缓解。

参与者一致认为,为每种类型的用户(管理员、自助服务/诊断和护士)设置单独的API网关将阻止来自管理员web用户界面或自助服务web用户界面的调用到达病历交换界面。架构师同意并创建了最终的架构,如图20-13所示。

图20-13.解决安全风险的最终架构变更

前面的场景说明了风险风暴的威力。通过与其他架构师、开发人员和关键利益相关者就对系统的成功至关重要的风险维度进行协作,可以识别出原本不被关注的风险区域。对比图20-9和图20-13,可以注意到风险风暴之前和之后架构的显著差异。这些重大的变化解决了架构中的可用性、可伸缩性和安全性问题。

风险风暴不是一次性的过程。相反,在任何系统的生命周期中都是一个连续的过程,以便在风险区域在生产环境发生之前捕获并减轻它们。风险风暴的举办频率取决于许多因素,包括变更频率、架构重构工作和架构的增量开发。通常在添加一个主要特性之后或在每次迭代结束时,会在某个特定维度上进行一次风险风暴。


原文参考:https://www.jianshu.com/p/b37ddf31f434

全书翻译目录:https://www.jianshu.com/p/05711d172dfa

上一篇下一篇

猜你喜欢

热点阅读