腾讯iOA研发实战系列(三)服务高可用实践 - 技术方案(CVM)篇
1. 导语
根据维基百科可用性、高可用性、可靠性、可用性和可维护性词条的解释。计算机系统的可用性(availability)是通过系统的可靠性(reliability)和可维护性(maintainability)来度量的。工程上通常用平均无故障时间(MTTF)来度量系统的可靠性,用平均维修时间(MTTR)来度量系统的可维护性。
可用性等级:
Level |
每年宕机时间 | 每天宕机时间 |
99.9 |
8.76小时 |
86分钟 |
99.99 | 52.6分钟 | 8.6分钟 |
99.999 | 5.25分钟 | 0.86秒 |
99.9999 | 31.5秒 | 8.6毫秒 |
高可用是指系统无中断地执行其功能的能力,代表系统的可用性程度。金融电信系统的可用性要求通常都在99.999%以上,iOA在业务实践中尽量看齐行业高标准。
在实践高可用时,需要考虑以下因素:
2. 腾讯iOA服务高可用目标和策略
2.1. 目标
不同的业务在高可用问题上遇到的问题会有差异,对高可用性的选择取决于许多因素,包括应用程序对业务的重要性、客户是否受到影响、应用程序的运行频率、受影响的用户数、数据库或应用程序故障转移到冗余系统的速度以及可以容忍的数据丢失量,
如金融结算系统要满足数据强一致性,推荐系统要满足推荐数据的准确性和时效性。
iOA作为企业服务,在服务高可用的目标是:保障核心功能持续快速地响应请求,尽可能少影响用户,容忍少量和短时的数据不一致。
2.2. 影响因素分析
要达成高可用目标,首先我们需要对影响高可用的因素做出分析,可能带来什么影响,再针对这些影响做出相应的应对策略。
(1)软件
软件本身存在bug从而影响服务可用性是很常见的问题,软件本身可能导致
单点故障:由于程序存在内存句柄泄露,死锁导致概率的不能响应请求,需要重启才能恢复
响应超时:软件在性能或者存在其他逻辑问题可能导致响应超时。
请求陡增:存在死循环或者周期任务等,在某些场景下可能会大量调用下游服务。
脏数据:由于程序逻辑问题,写入了脏数据。
(2)硬件
硬件故障在日常运维过程中也比较常见,机器的磁盘,主板,网卡均有可能出现故障。
单点故障:硬件故障导致部署在节点的服务不能响应请求。
数据丢失,数据不一致:磁盘故障导致数据丢失,或者主从数据不一致。
(3)环境
整个环境不可用出现的概率虽然很低,但是仍然有发生的可能性,如地震,水灾,施工导致的整个机房故障,导致的问题:
集群不可用:某个地区的机房同时出现问题,如果服务没有跨城市部署,则整个集群不可用。
(4)数据
因为软件,硬件,环境等因素可能导致数据丢失,数据不一致,脏数据等问题,逻辑服务可以重新部署,但是数据没有做好备份则不可恢复。
(5)网络
日常网络波动,网络策略变动,网络设备故障都会对服务可用性造成影响,可能的影响如下:
单点故障:单机网络故障或者策略不通
响应超时:由于突然流量导致网络拥堵,或者网络设备性能瓶颈,导致服务之间调用超时。
集群故障:机房网络出现故障,可能导致单个集群不可用。
综合分析各个影响因素,导致的问题有:①单点故障;②数据故障(数据丢失,数据不一致,脏数据);③集群故障;④突然异常(调用超时,请求突增)等问题。
2.3. 应对策略
2.3.1. 技术方案
综合上面分析的结果,首先需要在技术方案上进行设计,系统有良好的自愈能力,减少人工干预,做好数据备份,建设全面的监控,感知系统运行状态,对异常进行及时和准确的处理。
(1)单点故障自愈
自动识别出故障点,并将故障点快速隔离出系统。
(2)数据备份
数据采用主从或分片模式,通过热备和冷备,跨集群备份,定期备份等方式保证数据不丢失,发生故障时可切换,出现脏数据可回滚。
(3)集群故障可切换
整个集群不可用出现的概率虽然很低,但是仍然有发生的可能性,通过建设异地多活能力,数据在各个集群之间同步备份,在单个集群不可用时,具备整体切换的能力。
(4)异常场景应对
对可能出现的异常场景,如突发流量,调用超时,依赖服务故障,等场景提前做好应对设计,在出现异常时系统能自动容灾。
2.3.2. 流程规范
方案确定之后,如何保证方案能够在开发、测试、运维等各个环节得到很好地贯彻,确保故障发生时高可用措施能按预期生效,需要在流程规范上有相应的应对策略。
由于篇幅问题,流程保障策略目标和具体做法将在另外的篇章具体说明。
3. iOA服务高可用技术方案设计(CVM)
iOA后台服务一开始是基于CVM部署,近年随着云原生技术的发展,逐步往云平台迁移,本篇主要介绍iOA服务在CVM模式高可用建设的一些做法,基于云平台的高可用实践将在后续的篇章介绍。
3.1. 单点故障自愈
3.1.1. 服务拆分
要实现单点故障自愈,不能把鸡蛋放在同一个篮子里面,需要对服务拆分,降低服务复杂程度,解耦不同功能模块,降低单个服务故障对系统的影响。
根据iOA服务的业务场景,结合微服务服务拆分理念,将服务拆分为接入层 – 逻辑层 – 数据访问层 -数据层,具体如下:
接入层
接入层作为整个服务的流量入口,是实现服务高可用的桥头堡,通常的做法是将接入层设计为api网关模式,具备安全认证,接口鉴权等公共工作,同时具备流量灰度,限流频控,熔断降级等服务高可用能力。
逻辑层
对于模块和服务的划分应该遵循共享特定的模型,而不是共享内部表示这个原则,这样就可以做到松耦合。而松耦合可以保证可以独立的修改及部署单个服务而不需要修改系统的其它部分。
服务与服务之间通过接口调用,不需要了解其他服务的内部实现。服务上线下线基于名字服务自动完成。
数据访问层
数据访问层是一个特殊的逻辑层,各个业务逻辑服务不直接访问数据层,而是通过数据访问层,可以收敛数据层连接,解耦逻辑层与数据层。
数据层
集群模式,主从复制,数据异地备份。
在具体的服务拆分时,除了根据业务功能进行拆分,还应该考虑服务对可用性的影响程度,将影响程度不通的接口进行拆分,减少低优先级服务影响高优先级服务的可能性。
3.1.2. 服务冗余
集群中每一个服务都不能存在单点,否则单点故障时无法进行容灾。每一个服务都有冗余实例,多个实例同时承担请求,且这些实例部署在不同的服务器上,一旦单个节点发生故障可以将请求转移到其他实例上。
3.1.3. 故障恢复
服务冗余本身并不能保证高可用,必须要有一种机制来检测故障,在iOA的开发实践中,针对不同层级的服务,iOA分别采用了负载均衡,名字服务和选举倒换等故障恢复方法。
3.1.3.1. 负载均衡
通过接入负载均衡器来实现故障自愈,负载均衡器会定时探测接入层实例端口是否正常,单个服务节点异常时能及时隔离,通常在接入层使用负载均衡来容灾。
3.1.3.2. 名字服务
逻辑层的变动通常比较频繁,出现问题的概率也比较大,在业界主要是通过名字服务来实现服务自动上下线,故障时自动隔离。
服务在上线时进行服务注册,并与名字保持心跳连接,下线时名字服务能及时感知。主调服务通过名字服务获取被调服务列表,通过预设的策略选取被调服务实例进行服务调用。
3.1.3.3. 选举倒换
选举倒换适用于有状态服务,在iOA服务里面就是数据层。数据层使用集群模式,整体通过VIP向外提供服务,集群中各个节点相互watch,并通过KeepAlive,Raft,Paxos等协议进行选举倒换,并漂移VIP,调用方无需感知数据层倒换过程。
3.2. 数据备份
(1)集群模式,数据有主备备份,单点故障时可以倒换到其他机器,保证服务连续性
(2)跨集群热备:当集群整体不可用,可以切换到其他集群,服务不中断。
(3)定时冷备:当由于程序逻辑出现问题导致了脏数据,需要将数据回滚到指定状态,就需要对数据进行定时备份。
3.3. 集群切换
正常情况下,用户无论访问哪个地方的业务系统,都能够得到正确的服务。某个地方的业务异常时,用户访问其他地方的业务系统,能够得到正确的业务服务。异地多活能够保证火灾、地震等灾害情况下,当某个地区的业务失效时,业务能够通过其他地区得到服务而不受影响。
对于异地多活,最主要是做好各个集群之间的数据同步,这样用户在不同集群之间可以平滑切换,现在的数据层服务如redis,mysql等都提供数据同步的功能。
在多集群调度中,用户接入哪个集群需要一个调度策略。目前iOA提供两种方式,一种是在iOA客户端提供用户手动选择的入口,如下图所示:
3.4. 异常策略
服务上线之后,由于自身服务或者调用方服务bug、依赖方故障、网络波动、设备故障、热点事件,从而带来调用超时、突发大流量,从而影响服务可用性,要保证服务可用性,需要针对这些异常场景做相应设计,让系统能够自动处理这些场景。
从iOA的开发实践结合业界做法,主要有如下措施:
3.4.1. 超时管理
自身服务和依赖方服务都可能存在超时,需要对每次请求进行超时管理,避免请求堆积导致服务过载
(1)被上游调用超时管理,自身服务异常时,快速返回,避免请求积压。
(2)调用下游服务,一定时间未返回,终止等待,返回错误,根据场景决定是否发起重试。
3.4.2. 请求频控
频控系统在业务请求量突增(如突发热的事件),这时候后台服务承受巨大的请求压力,需要频控系统来对流量进行削峰,提供后台微服务的过载保护和防雪崩。所谓频控简单的说就是在让请求处理在一段时间内控制到只有N次。请求频率控制的做法有如下方法:
(1)后台服务具备一定事件内请求次数,具体又可以分为单季频率控制和全局频率控制。
(2)客户断缓存,数据拉取:将一些数据缓存到客户端,再周期请求后台更新,减少拉取次数;数据上报:客户端本地做变化检查,发生变化时上报后台,减少上报次数
(3)后台控制请求频率,需要周期拉取或者上报的数据,由后台来控制拉取和上报周期。
3.4.3. 服务熔断
熔断这个词来源于电子工程中的断路器。在微服务架构中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用,避免问题扩大。在实践中可以从如下两个方面来设置熔断规则:
(1)基于错误率,当下游接口访问错误量达到一定比例时;
(2)基于名单,往下游推送名单,当名单数达到一定数量时。
3.4.4. 服务降级
所谓服务降级就是当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,我们可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
说到底,就是在异常突发的业务流量增长导致整体后台服务不可用时,将一些旁路服务或者非关键逻辑去掉,保证核心服务能够工作。
服务降级也有很多手段可以使用,包括:
-
容错降级 -
静态返回值降级 -
旁路服务降级
3.4.5. 数据缓存
对于依赖的第三方服务,数据实时性要求不高的,在iOA的业务场景中,如网段数据,员工组织架构数据,可以本地缓存一份数据,定期更新本地缓存,优先访问本地缓存数据,缓存未命中时访问第三方服务,减少第三方系统对服务可用性的影响。
4. 结语
本文主要介绍了iOA后台在传统的CVM运行方式时,服务高可用上的设计思路和保障方法。
技术一直在变更,云原生是当前领先的业务开发模式,演化成一个庞大的生态,在云平台能力的加持下,构建高可用服务在技术方案会些不同,
同时高可用永远不是一蹴而就的事情,设计的高可用措施,如何确保在故障发生时能够生效,需要日常开发测试运维的过程,通过流程来保障。
后续将介绍iOA在云原生技术下服务高可用的一些实践经验,以及iOA在服务高可用性上的开发测试流程管理、运维保障方面的做法,敬请期待。
-END-
点击关注“腾讯IT技术”
探索前沿领域技术,获悉腾讯实践经验