论软件可靠性设计技术的应用

随着软件的日益普及,系统中软件成分不断增加,使得系统对软件的依赖越来越强。软件的可靠性对系统可靠性的影响越来越大。而实践证明,保障软件可靠性最有效、最经济、最重要的手段是在软件设计阶段采取措施进行可靠性控制,为此提出了软件可靠性设计的概念。软件可靠性设计就是在常规的软件设计中,应用各种方法和技术,使软件设计在兼顾用户功能和性能需求的同时,全面满足软件的可靠性要求。软件可靠性设计应和软件的常规设计紧密结合,贯穿于软件设计过程的始终。

请围绕“软件可靠性设计技术的应用”论题,依次从以下三个方面进行论述。

  1. 概要叙述你参与管理和开发的软件项目以及你在其中所承担的主要工作。
  2. 结合项目实际,论述你在项目开发过程中,进行软件可靠性设计时遵循的基本原则;论述你在该项目中所采用的具体可靠性设计技术。
  3. 阐述你在具体的可靠性设计工作中,为了分析影响软件可靠性的主要因素,所采用的可靠性分析方法。

试题出自试卷《2013年下半年系统架构设计师考试论文真题》

摘要

2018年9月,我所在的部门因公司业务发展需要,承担了公司的实时消息平台的研发工作。该平台提供了即时通讯、消息推送、社交圈等功能,满足C2C(用户对用户)、C2B(用户对商家)、B2C(商家对用户)的沟通需求,同时为公司内其它业务子系统间消息流转提供支持。我在该项目中担任系统架构设计师的职务,主要负责设计平台的系统架构和技术选型。本文以该系统为例,主要论述了软件系统可靠性的具体应用:通过架构设计风格降低软件系统的复杂度;通过集群和负载均衡技术实现系统容错;通过程序防卫式编程技术解决软件的容错和避错。事实证明,采用这些技术后,系统在可靠性、可扩展性、可用性等方面都达到了预期目标。系统自2019年2月上线后运行平稳,得到了领导和用户的一致好评。

正文

随着移动互联网技术的迅猛发展,我所在的公司的在各业务子系统的开发过程中发现,用户、商户、客服之间进行沟通的需求越来越大,各业务子系统间进行消息流转的需求愈加频繁,且使用起来十分繁琐不便。为此,公司于2018年9月开始研发设计通用的实时消息平台(以下简称为“系统“)。该系统致力于为公司内各业务产品线提供基础通用的消息服务,降低公司内各业务子系统间进行信息交互的复杂度,满足C2C(用户对用户)、C2B(用户对商家)、B2C(商家对用户)的沟通需求。该系统为C端用户提供了私聊、群聊、密聊、聊天室、漂流瓶等多形式多场景的即时通讯功能,同时,该系统还支持公司内各业务子系统间进行消息流转,如B端商家通过该系统可以定向地为用户实时推送各种业务消息,如订单消息、活动促销消息等。

我作为单位技术骨干之一,主持并参与了项目计划制定、需求分析、整体架构设计与技术选型、底层设计、部分编码等多项工作。下面,我将首先介绍几种目前比较主流的软件可靠性分析和设计技术,然后详细介绍“消息平台”的分析和设计过程中所采用的可靠性设计技术及其原因。

在软件可靠性设计之前,需要采用软件可靠性分析和预测方法,来确定当前系统中的主要可靠性因素和目标。常见的可靠性分析方法包括故障树分析方法、失效模式与效应分析方法等。我在项目实践中,带领团队采用故障树分析方法进行可靠性分析。故障树分析方法是一种自顶向下的软件可靠性分析方法,从软件系统不希望发生的事件向下逐步追查导致事件发生的原因,直至基本事件,从而确定软件故障的原因。经过团队分析,我们找出了以下可能导致故障发生的几个主要因素:

一、运行环境:由于我们的应用是部署在第三方公有云上,系统所依赖的运行硬件是第三方云服务厂商提供,并不是完全可靠的,且厂商只提供了基本的服务器主机,外围安全环境(防火墙、集群搭建等)需由我们自己的运营团队负责维护;

二、软件规模及内部结构的复杂度:软件规模大小程度、内部结构复杂程度,都会影响系统的可靠性和开发测试的难度。因此,我们需要尽量降低主流程的复杂度,让整个架构实现更加可控;

三、开发人员水平:团队中各开发人员编码水平不一,对整个系统的业务理解层次也不一样,开发出的系统中难以避免会出现各类bug,进而影响系统的可靠性。

在完成可靠性分析后,我们接着评估了主流常见的可靠性设计技术:容错设计检错设计降低复杂度设计等。软件容错技术主要有恢复块设计、N版本程序设计和冗余设计三种方法,主要适用于软件失效后果特别严重的场合。恢复块设计就是选择一组操作作为容错设计单元,从而把普通的程序块变为恢复块。一个恢复块中包含有若干功能相同、设计差异的程序块,每一时刻有一个程序块处于运行状态,一旦某程序块出现故障,则用备份程序块予以替换。N版本程序设计的核心是通过设计出多个模块或不同版本,对于相同初始条件和相同输入的操作结果进行多数表决,防止因其中某一软件模块的故障而提供了错误的服务,以实现软件容错。软件冗余设计技术是采用多种不同路径、不同算法或不同实现方法的模块或系统作为备份,在出现故障时进行替换,维持系统的正常运行。检错设计主要应用于无需在线容错的地方或不能采用冗余设计技术的部分,出现故障后及时发现并报警。降低复杂度设计的思想就是在保证实现软件功能的基础上,通过简化软件结构,缩短程序代码长度,优化软件数据流向,来降低软件复杂度,从而提高软件可靠性。

由于消息平台的核心功能是为业务子系统传递消息,对可靠性有着较高的要求,一旦系统出现故障,将影响其它业务子系统的正常运行。我根据系统本身的特点,结合以上几点影响软件可靠性的主要因素,采取了提高系统可靠性的三点措施: 

一、应用分层架构设计风格,降低软件设计的复杂度。 好的设计是成功的一半,在进行系统架构设计时,我认为采用分层架构比较符合实际情况。我通过技术调研和讨论分析,决定采用分层架构风格,将系统划分为接入层,逻辑层,数据层。其中,接入层负责处理来自客户端(PC/H5/App)的连接、断开请求,它不含具体的业务逻辑,因此可以实现动态水平扩展;逻辑层负责实现核心的消息处理逻辑,如私聊、群聊、密聊、漂流瓶、聊天室、消息推送等核心业务场景的实现;数据层负责提供数据存储访问服务,如数据库服务,缓存服务,文件服务,搜索服务等。系统层次结构清晰,各层职责明确,降低了系统的复杂度和维护成本。

二、集群和负载均衡技术实现系统容错。 我们采用了集群部署的方式,来提升应用系统的可靠性。由于我们系统采用了前后端分离的方式构建,前端采用主流的Vue框架,后端采用Gin框架。前端相关的Vue页面经过编译后,会生成html、javascript、css等静态资源,这些静态资源会部署在由两个Nginx实例组成的集群中。为了便于访问和提高Nginx集群的可靠性,Nginx集群的两台主机配置了VIP,同时通过keepalived实现双机热备。消息平台的接入层是无状态的,可以通过水平扩展的方式在业务高峰期提升处理能力,整个应用系统的部署架构上不存在单点故障。在数据层,为了解决MySQL的高可用问题,我们采用一主两从的主从部署模式,主节点负责读写操作,从节点只负责读操作,提高数据访问性能和效率。当主库发生问题时,可快速由其他的从库升级为主库,继续服务,达到容错的效果。

三、通过防卫式编程进行软件的容错与避错。 根据以往的架构经验,系统的不可靠大部分是由于程序内部的设计或者网络请求参数的配置或者连接池参数的配置不当所导致的,所以通过程序设计方面进行软件的容错是非常重要的。在程序设计方面的容错用的最普遍的就是防卫式程序设计。该系统在业务逻辑层的API接口中采用panic/defer/recover机制捕获异常,然后转换成统一的异常编码和描述信息,防止直接将业务异常和程序异常暴露给用户,提高用户的系统感知。同时在系统出现故障时,通过异常编码能快速地定位到后端具体的异常堆栈信息。为了解决网络或对方服务不稳定等因素的影响,我们采用了重试机制,如果出现接口调不通的情况,会分3次,每次按30秒、1分钟、2分钟逐级重试,如果3次都调不通,则跳过该次调用,等待下一次调用。

结尾

最终项目成功上线,凭借软件设计过程中出色的可靠性设计,系统正常运行了近一年,收到各方好评。通过本次开发实践,我明白了软件的可靠性在实际应用中的重要地位,学习了提高可靠性相关的分析方法和设计技术,也深刻体会到了系统架构设计中可靠性和安全性的重要性。这些都是我在今后的系统架构设计工作中需要注意与改进的地方,也是日后我应该努力的方向。

彦祖老师 wechat