在软件系统里面,功能性需求是面向用户、详细明确的需求,由产品人员根据市场的需要提炼出来,是产品生命周期里最重要的一环。比如电商系统里面的优惠券功能,通常包含需求:优惠券分类、细分领券人群、核销优惠券等等。一旦需求通过技术评审,开发人员必须依照文档实现功能,不允许轻易变更。
非功能性需求是什么呢?保障系统持续健康运转的辅助需求。依然以电商系统的优惠券为例,在促销活动期间发放大量优惠券,如何防止用户集中领券时系统不崩盘呢?活动结束后,如何收缩服务器,节省服务器资源呢?非功能性需求是面向运维的,重要但是不太紧迫,有时候可以没有操作界面,由架构师提出解决方案,再推动各个业务开发部门去接入相应组件。这些辅助系统对业务系统性能影响很小,并且长期处于优化状态。
可伸缩性是指系统根据外部负载自动调节计算能力,常见的做法是水平扩展和垂直扩展。
当系统负载很高时,增加服务端的节点数量,也叫做扩容;当负载很低时,释放闲置的机器,也叫做缩容。这两个过程有几个重要的思考点:
(1)节点越多,承载能力越高吗:任何事情都有两面性,为了解决问题引入一个方案,就必然带来新的问题。节点越多,协调节点的开销就越大,额外增加的计算资源抵不上协调节点的开销,并发能力不升反降。
(2)扩容多少节点才够用:资源总是有限的,用有限的资源做更多的事情,才能得到资本家的欢心。合理扩容的数量根据压测的结果来定。在日常的运维中,要求系统能够自动化扩容少量机器处理突发流量,如果超出负载再发出警报。
垂直扩展是指增强单机处理能力,比如增加内存、升级CPU、更换固态硬盘等等。这个做法的好处是简单快速,无需调整系统设计;缺点是单机的处理能力始终有限,不可能无限升级,而且更换硬件必须停机,影响系统可用性。
系统可用性是指系统在规定的时间内正常运行的能力,是衡量系统质量和稳定性的重要指标之一。例如,一个系统的可用性为99.9%,表示在一年中的时间里,系统正常运行的时间占据了99.9%。以下是计算公式:
AvAIlability = (Total Time - Downtime) / Total Time * 100%
Total Time表示总的时间,Downtime表示系统的停机时间。
除了自然灾害如水灾、地震等不可抗因素,降低可用性的主要原因是:
对于大型互联网公司尤其是SaaS、云服务等公司,系统可用性就是生命线,只要出现时间过长的服务不可用,会大大影响口碑和品牌。通常这类公司采取的技术措施是异地多活,在不同城市建立独立的数据中心。“活”是相对于冷备份而言的,冷备份是备份全量数据,平时不支撑业务需求,只有在主机房出现故障的时候才会切换到备用机房,而多活,是指这些机房在日常的业务中也需要做业务支撑。
可维护性是衡量系统升级的能力,修改或者增加需求,开发周期越短越好,注意与“可伸缩性”区分。
需求变更是无比寻常的事情,可维护性是所有团队都会关注的重点。一旦系统的可维护性变差,程序员的头发会迅速脱落。影响可维护性的因素主有三个:
近些年在大型项目开发里,领域驱动设计(Domain Driven Design)的出镜率很高。领域驱动设计是一套从系统分析到软件建模的设计思想和方法论。核心思想是以领域为核心驱动力构建软件设计体系,并围绕业务概念抽象出领域模型,通过领域和边界划分将复杂的业务模型抽象化、简单化,最终实现复杂软件应用系统的拆解和封装。领域驱动设计并没有发明新的东西,每个概念都是沿用已久的软件开发理念。它的实施成本很高,项目代码更加繁琐,人员的沟通成本也较高。
如果团队规模很小或者开发小型项目,提高可维护性至少要做好两个事情:
数据是系统最重要的资产,数据不能丢也不能错,保持数据一致性万分重要。一致性分两种情况:
在分布式系统中,保持数据一致性是公认的难题,主要体现在下面几点:
保持强一致性的成本很高,最好的解决方案就是避免分布式事务,但是在金融、电信领域中的部分业务场景要求数据强一致性,同时要保证服务的可扩展性和可靠性。结合实际的业务场景,一致性可以细分五个级别:
弹性,是指系统可以优雅地处理意外、从故障中恢复过来。故障是不可避免的,甚至不可预测。由于微服务的普及,故障发生的几率与计算节点数量成正比。分布式系统具备一定的容忍故障的能力,故而弹性设计又称容错设计,主要的解决方法有如下两点:
系统必须具备防止故障从一个系统传播到另一个系统的能力,常见场景如下:
(1)系统间强依赖:如果系统间存在强依赖,当一个系统发生故障时,强依赖它的组件将无法正常工作。通常的手段是将强依赖转化为弱依赖或最弱依赖,比如设置合适的超时、捕获异常、同步依赖转异步依赖、提供备份组件等。
(2)系统共享资源:如果系统间存在共享的资源,如线程池、数据库连接池、网络连接池、内存区等等。当一个系统因为故障耗尽了共享的资源后,所有依赖该资源的系统也都会发生故障。通常的手段是对组件的资源使用建立配额体系,或者为重要组件提供专用资源。
(1)服务降级:当出现系统故障后,在有限的资源情况下牺牲某些业务功能或者某些客户群体,保障更关键的业务服务质量。服务降级可以是人工触发的,也可以是系统自动执行的。所有核心交易场景下的非关键服务访问均应进行服务降级设计,以保证核心交易成功率。
(2)服务限流:当负载超出系统处理能力时,可能会造成系统部分业务失败,需要通过业务限流来防止系统进一步化。例如在一个分布式系统中,每秒最多只能处理2000个请求。为了防止系统过载,可以设置规则限制上游服务请求量,当超过2000时随机抛弃一些请求来实现限流。
(3)服务熔断:微服务与微服务之间有依赖性,可能导致故障传播,对整个系统造成灾难性的后果,即服务的雪崩效应。熔断器是通过快速失败(Fail Fast)的机制,避免请求大量阻塞,从而保护调用方。比如:服务A调用当下游B失败时,会导致请求超时引起堆积队列,进而加大了B系统的压力,增加了整个链路的请求时间。B系统本身就出现了问题,不断的请求又把问题加重了。如果使用了A触发了熔断,拒绝了上游的请求,会降低下游B服务的压力,给与B服务恢复的时间。
6.可观察性
可观测性是指通过度量、监控和分析系统组件,了解系统的状态、性能和问题的能力。可观测性可以帮助开发人员快速定位和解决系统中的问题,提高系统的稳定性和可靠性。系统可观测性设计还有助于优化系统性能,帮助研发人员针对性地做出调整和优化,提高系统的吞吐量和响应速度。系统可观测性设计应遵循几个重要原则:
主流的可观察系统基于三类数据构建,覆盖了一个应用服务器产生的大部分数据:
可观察性系统是监控系统的超集,监控能够检测到系统当前的问题,但是可观察性系统要帮助研发人员预判故障发生的可能性。
安全性是指保障硬件正常运行,让用户只能访问合法授权的资源。安全是架构设计中很重要的一部分,很多大型企业都因为安全漏洞泄露过数据。广义的安全性涉及到所有的软硬件,比如物理机房、服务器及网络、操作系统、应用系统。架构安全设计可以遵循如下五个原则:
系统安全等级越高,运作成本越高。为了节省成本,中小型团队主要聚焦应用系统的安全,其他的交给云服务。云服务商负责云端安全,尤其是用于托管资源的物理基础设施的安全,包含如下内容:
开发团队根据自身人力和财力,酌情实施安全设计,通常可以借鉴的安全措施有5条: