二、应用高可用设计要点
高可用是一个综合的解决方案,并不是通过简单的一个技术、一个产品就能做到的。为了实现最终交付系统的高可用,我们在应用系统的架构设计和代码设计时有很多考量。
1.消除单点
云原生最核心的优势是弹性伸缩,通过横向扩展来解决应用容量的瓶颈,实现资源投入和应用容量的准线性增长关系。为了达到更加精细化的应用弹性,我们在系统设计过程中做了应用分层、分布式设计、微服务架构设计。
一个应用系统要实现真正的分布式,所有的层次都必须做到分布式,即从流量接入到服务调用、数据存储、缓存、消息队列、对象存储等,都必须是分布式,没有任何一个环节存在单点的问题,这样的系统才具备良好的弹性能力。
2.无状态化
为了实现应用容量的横向扩缩容,服务设计为可伸缩且可部署到任意敏捷基础设施中,此总体原则的一个推论就是,服务不应为有状态的。
无状态化并不意味着应用系统完全没有状态,而是通过状态外置来实现可伸缩部分服务的无状态化。整个架构分为无状态部分和有状态部分,而业务逻辑部分往往作为无状态部分,而将状态保存在有状态的中间件中,如缓存、数据库、对象存储、大数据平台、消息队列等,这就是我们常说的状态外置。这样无状态部分可以很容易地横向扩展。
3.幂等设计
幂等一般针对后台服务而言,“服务幂等性”是指针对某一服务的多次调用,只要请求的参数是一样的,那么服务返回结果一定是一致的,且后台系统不会因为多次调用而产生任何副作用。
在分布式环境下,前端应用的一次请求可能会调用多个后台服务,可能会发生某些后台服务超时或者网络闪断等情况。这时为了保证业务的成功,前端应用一般会通过重试的机制达到数据的最终一致性。因此,在云原生分布式微服务架构下,服务幂等设计是作为一种解决应用高可用和数据一致性的基本实践手段。
4.弹性伸缩
弹性伸缩包括弹性扩展和弹性收缩,是实现应用高可用的重要技术手段。在业务高峰期,当系统负载较大时,通过横向扩展新的应用节点或者拉起新的容器来分摊原有压力节点上的负载,让系统平稳渡过前端应用高并发流量的冲击。而在业务低峰期,通过释放部分应用节点以提高资源的有效利用率。
弹性伸缩分为手动弹性伸缩和自动弹性伸缩。手动弹性伸缩是运维人员通过观测资源的水位或者收到资源告警信息后,人工为应用集群添加新的服务节点来解决资源负载过高的问题。自动弹性伸缩则是系统根据管理员预先设置的规则自动触发进行资源节点的动态管理。
5.容错设计
容错性是指软件检测应用程序所运行的软件或硬件中发生错误并从错误中恢复的能力,通常可以从系统的可靠性、可用性、可测性等方面来衡量。为了消除单点故障,应用部署时采用集群部署、分布式部署,都是为了把软硬件故障给应用系统带来的影响降到最小。容错设计分为应用、系统、服务等不同的层面。
容错设计还有一个很重要的思路——冗余设计,通过一定的额外成本投入换取系统的可靠性提升,包括资源冗余(防止不可预期的业务增长对于系统的压力)、数据冗余(防止核心数据异常丢失)、架构冗余(如双通信链路)。
6.同步转异步
在一定程度上,同步可以看作单线程,这个线程请求一个方法后就等待这个方法给它回复,否则它不往下执行。异步可以看作多线程的,请求一个方法后就不管了,继续执行其他的方法。在实现方面,通常把同步的请求通过消息队列转成异步化订阅处理,以减少系统之间的耦合,避免核心应用被非核心应用拖垮。同时,消息队列起到了很好的削峰填谷的作用,让瞬间的高并发请求有一个缓冲,从而保护后台应用系统的平稳运行。
7.缓存设计
缓存的主要作用是降低应用和数据库的负载,提高系统性能和客户端访问速度。在架构和业务设计上,可以考虑将访问量较大、不经常修改的(如字典表和系统参数),或对数据库性能影响较大的查询的结果进行缓存,以提高系统整体性能。
8.动静分离
动静分离是指静态页面与动态页面分开在不同的系统上访问的架构设计方法,静态资源(如 html、js、css、img 等)与后端服务分离部署。静态资源放在 CDN、Nginx 等设施上,访问路径短,访问速度快(几毫秒);动态页面访问路径长,访问速度相对较慢(数据库的访问、网络传输、业务逻辑计算),需要几十毫秒甚至几百毫秒,对架构扩展性的要求更高。
9.流控降级
无论一个系统的容量预估做得多么充分,我们总是无法避免一些不可预期的并发流量的冲击。这些流量既可能是正常的业务流量,也可能是非法的攻击行为。流控降级相当于给后端应用系统上了一道保险,让系统具有一定的抗压能力,被广泛用于秒杀、消息削峰填谷、集群流量控制、实时熔断等场景中,从多个维度保障客户的业务稳定性。
流控降级包括流控和降级两个概念。流控,即流量控制(flow control),根据流量、并发线程数、响应时间等指标,把随机到来的流量调整成合适的形状,即流量塑形,避免应用被瞬时的流量高峰冲垮,从而保障应用的高可用性。熔断降级会在调用链路中某个资源出现不稳定状态(例如调用超时或异常比例升高)时对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误。
10.应用健康检查
应用健康检查是弹性伸缩和弹性自愈的基础,传统的负载均衡只能根据 IP:port 来进行节点探活,但无法处理应用假死的情况。应用健康检查是为了确保当前节点的应用能够正常对外提供服务,一旦应用健康检查失败,管控节点(如负载均衡、服务注册中心、K8s 管控等)必须及时把该故障节点摘除,防止请求再打到故障节点而导致业务失败。
11.优雅上下线
优雅上下线是实现业务 7×24 小时不间断运行的重要保障。为了实现应用版本变更的发布过程对在线业务的无感知,应用发布时我们一般采用分批发布的策略。
优雅下线是指应用节点平滑下线,停应用之前会有一段时间的“静默期”(如 10s),静默期内负载均衡不会再把新的请求打到该节点,同时该节点已经接收到的请求能够正常处理完。通过这种机制实现节点下线过程对业务平滑无感。
12.快速失败设计
面向失败设计原则是所有的外部调用都有容错处理,我们希望失败的结果是可预期的、经过设计的。系统发生异常时能够快速失败,然后快速恢复,以保证业务永远在线,不能让业务半死不活地僵持着。
版权声明: 本文为 InfoQ 作者【穿过生命散发芬芳】的原创文章。
原文链接:【http://xie.infoq.cn/article/051efb54ed4399a016bfc3ab8】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论