微服务架构如何避免大规模故障?

简介: 微服务架构通过一种良好的服务边界划分,能够有效地进行故障隔离。但就像其他分布式系统一样,在网络、硬件或者应用级别上容易出现问题的机率会更高。服务的依赖关系,导致在任何组件暂时不可用的情况下,就它们的消费者而言都是可以接受的。为了能够降低部分服务中断所带来的影响,我们需要构建一个容错服务,来优雅地应对特定类型的服务中断。

微服务架构通过一种良好的服务边界划分,能够有效地进行故障隔离。但就像其他分布式系统一样,在网络、硬件或者应用级别上容易出现问题的机率会更高。服务的依赖关系,导致在任何组件暂时不可用的情况下,就它们的消费者而言都是可以接受的。为了能够降低部分服务中断所带来的影响,我们需要构建一个容错服务,来优雅地应对特定类型的服务中断。


本文基于一些在RisingStack的顾问咨询与开发经验,介绍了如何运用一些最常用的技术和架构模型,去构建与维护一个高可用的微服务系统。


如果你不熟悉本文中的模式,并不意味着你做错了什么。毕竟构建一个高可用的系统需要很多额外的付出。


*微服务架构的风险 The Risk of the Microservices Architecture


微服务的架构将应用的逻辑移动到一个服务里面,服务之间通过网络层进行通信交互。通过网络通信交互的方式取代了内存的调用,同时需要多个物理和逻辑组件之间的相互协作,给系统带来了额外的延迟性与复杂性。分布式系统复杂性的增加,导致了特定网络故障的可能性变得更大。


微服务允许你实现优雅的服务降级,因为组件可以被单独的设置为失败。


团队可以独立地设计、开发与部署他们的服务,是微服务的最大优点之一。他们完全拥有整个服务的生命周期,这也意味着团队无法控制他们的服务依赖,因为这些服务更有可能是不同的团队在管理。我们需要记住,提供者的服务由于发布中断、配置等等其他的改变而暂时不可用,他们是由别人控制,并且组件之间独立活动。


*优雅的服务降级 Graceful Service Degradation


微服务最佳优势之一,当某个组件单独失败时,你可以实现优雅的服务降级,进行故障隔离。例如,一个照片共享的应用,由于中断,用户可能无法上传新的照片,但他们仍然可以浏览、编辑和分享他们现有的照片。


image.png


在大多数情况下,在一个分布式系统中,应用程序之间互相依赖,实现一种优雅的服务降级,这是很困难的,你需要采取多种故障切换逻辑(其中一些会在本文后面进行讨论),应对临时的故障与中断。


image.png


*变更管理 Change management


谷歌网站的可靠性团队(SRE)发现,大约70%的中断是由一个实时系统的改变而引起。当你在服务中更改某些内容时——你部署了新版本的代码或更改了一些配置——总会导致更高的失败机率或者引入一个新的bug。


在微服务架构中,服务之间彼此依赖。这就是为什么你应该尽量减少失败,并限制它们的负面影响。如果要处理来自变更的问题,你可以使用变更管理策略和自动升级。


例如,当需要部署新代码或者更改某些配置时,你应该逐渐地将这些更改应用于实例的子集,监控它们,甚至当你看到关键指标有负面影响时,它们会自动回滚恢复。


image.png


另一个解决方案,就是运行两个生产环境。只部署其中一个,并且在验证新版本的运行符合预期之后,才会将负载均衡指向新版本。这被称为蓝绿色部署,或红黑色部署。


恢复代码不是一件坏事情。你不应该把坏的代码留在生产中,然后再思考哪里出了问题。必要的时候,总是要恢复你的改变(回滚),越快越好。


*健康检查与负载均衡 Health-check and Load Balancing


实例会因为失败、部署或自动伸缩,而不断地启动、重新启动和停止。这会导致服务暂时或永久不可用。为了避免问题,你的负载均衡应该跳过不健康的实例,因为它们不能满足你的用户或子系统的需要。


应用实例健康可以通过外部观察来决策。你可以反复调用 GET /health 请求埋点或自身报告。现代服务发现解决方案,将不断从实例中收集健康信息,并配置负载均衡以保证健康的组件路由流量。


*自愈 Self-healing


自我修复可以帮助恢复应用程序。我们谈论的自愈,是指应用程序可以做一些必要的步骤来恢复崩溃状态。在大多数情况下,这样的操作是经由一个外部系统来实现的,它会监控实例的健康,并在它们较长时间处于错误状态的情况下,重新启动应用程序。自愈是非常有用的,但是在某些情况下,不断地重启应用程序会引起麻烦。由于负载过高或者数据库连接超时,你的应用程序不停的重启,会导致无法提供一个正确的健康状态。


实现一种为微妙的情况而准备的高级自我修复解决方案,可能会很棘手,比如数据库连接丢失。在这种情况下,你需要为应用程序添加额外的逻辑来处理一些极端情况,并让外部系统知道不需要立即重启实例。


*故障切换缓存 Failover Caching


服务通常会因为网络问题和系统的变更而失败。由于自愈和先进的负载均衡,大多数中断只是暂时的,然而我们还应该找到一个解决方案,让我们的服务在这些故障中能够正常工作。这就是故障切换缓存,它可以帮助应用程序提供一些必要的数据。


故障切换缓存一般使用两个不同的过期时间。设置一个较短的时间,显示在正常情况下可以使用多长时间的缓存;设置另一个较长的时间,显示在发生故障期间,可供使用缓存数据的时间会有多久。


image.png


很重要的一点是,只有当过时的数据比什么都不做要好的情况出现时,才可运行故障切换缓。


可以通过使用HTTP中的标准响应头(response header)来设置缓存和故障转移缓存。


例如,通过设定 header 参数 max-age 来指定一个资源被刷新时最大时间;也可以通过设定 header 参数 stale-if-error 来决定,在服务失败的情况下,需要多长时间从缓存获取数据。


现代的CDN和负载均衡器提供了各种缓存和故障切换的方式,你也可以为公司建立一个包含了统一的可靠性解决方案的共享标准库。


*重试机制 Retry Logic


在某些特定的场景下,我们可能无法缓存数据,或者我们想对其做出一些更改,但是我们的操作最终还是会失败。在这些情况下,我们可以重新尝试我们的操作,因为我们可以预计资源在一段时间后会恢复,或者我们的负载均衡将我们的请求转发到一个健康的实例。


在应用程序和客户端添加重试逻辑需保持谨慎,因为大量的重试会让事情变得更糟,甚至会阻止应用程序的恢复。


在分布式系统中,微服务系统重试会触发多个其他的请求或重试,引起一个级联效应。为了尽量减少重试带来的影响,你应该最大限度限制它们的发生次数,并使用指数补偿算法来持续增加重试之间的延迟。


重试由客户端(浏览器,其他微服务等)发起,客户端不知道这个操作是在处理请求之前失败还是之后失败的,你应该准备好应用程序来处理幂等性(idempotency)。例如,当操作重试购买时,不应该对用户进行重复扣费。对于每个事务,使用唯一的 幂等令牌(idempotency-key ),可以帮助处理重试。


*限流与降级 Rate Limiters and Load Shedders


限流是指在一个时间段内,特定的用户或应用程序可以接收或处理多少请求的技术。例如,有了限流,你就可以找出引起流量高峰的用户和微服务,或者可以确保应用不会在负载过高情况下,发生自动扩容都不能拯救。


你还可以限制业务优先级较低的流量,以便为核心业务提供足够的资源。


image.png


另外一种类型的限速器称为并发请求限制。当有一些昂贵的端点不应该超过指定的调用次数,但你仍然希望提供流量服务时,选择这样的操作是很有用的。


快速降级可以确保总是有足够的可用资源去服务关键的事务。它为高优先级请求保留一些资源,并且不允许低优先级事务使用所有的资源。降级与否是根据系统的整个状态进行判断的,而不是基于单个用户的请求桶大小。服务降级用于帮助恢复系统,当发生一些事故时,它们可以保证核心功能仍然继续工作。


如需获取更多有关限流与降级的信息,推荐前往https://stripe.com/blog/rate-limiters,阅读Stripe的文章。


*快速且独立地失败 Fail Fast and Independently


在微服务体系结构中,我们希望我们的服务能够快速、独立地失败。为了在服务级别上隔离问题,我们可以采用舱壁模式(bulkhead pattern)。你稍后可以在这篇文章中读到更多关于舱壁的信息。


我们还希望我们的组件快速失败,因为我们不想等待坏的实例超时。没有什么比一个挂着的请求和一个没有响应的UI更令人失望的了。这样不仅浪费资源,而且还会对用户体验造成影响。我们的服务是相互调用的,所以更应该额外注意,在这些延迟结束之前,阻止挂起操作。


第一个想到的想法是在每个服务调用上运用一个较好级别的超时时间。这种方法的问题在于,你不可能真正知道什么是一个好的超时时间值,因为在某些情况下,网络故障和其他问题只会影响到一两个操作。在这种情况下,如果只有少数几个请求超时,你可能不想拒绝这些请求。


我们可以说,在微服务中使用超时来实现快速失败的例子是一种反模式,你应该避免它。你可以依赖于操作成功/失败统计数据的断路器(circuit-breaker)模式,而不是超时。


*舱壁 Bulkheads


舱壁被用来将一艘船划分成多个部分,这样就可以在船体破裂的情况下对部分封闭。


隔离壁的概念可以应用于软件开发中,做到资源隔离。


通过采用舱壁模式,我们可以保护有限的资源不被耗尽。例如,如果我们有两种操作,它们与相同的数据库实例交互,我们的连接数量有限,那么我们可以使用两个连接池,而不是共享连接池。由于此客户端资源分离,当发生超时或者过度使用连接池的操作,不会导致所有其他操作的关闭。


泰坦尼克号沉没的主要原因之一,就是它的舱壁有一个设计上的失败,水可以通过舱壁顶部上的甲板注入,淹没整个船体。


image.png


*断路器 Circuit Breakers


为了限制操作的持续时间,我们可以使用超时。超时可以防止挂起操作并保持系统响应。然而,在微服务通信中使用静态的、微调的超时是一种反模式,因为我们处在一个高度动态的环境中,几乎不可能发现正确的时间限制,以确保在每个场景下都能很好地工作。


我们可以使用熔断来处理错误,而不是使用小的特定事务的静态超时。断路器是以真实世界电子元件命名的,因为它们的行为是相同的(简单的说,这种模式主要是参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾)。你可以保护资源,帮助他们用断路器恢复。它们在分布式系统中非常有用,因为重复的失败会导致滚雪球效应(snowball effect),导致整个系统瘫痪。


当一个特定类型的错误在短时间内多次出现时,断路器就会打开。断路器的打开,阻止了进一步的资源请求——就像真的阻止了电流的流动。断路器通常在一定时间后关闭,为基础服务提供足够的空间来恢复。


请记住,并非所有的错误都应该触发断路器。例如,你可能希望跳过客户端问题,比如跳过 4xx 状态码响应的请求,但不包括 5xx 服务器端错误的请求。一些断路器也可以有半开状态,在此状态下,服务发送第一个请求检测系统的可用性,同时让其他请求失败。如果第一个请求成功,它将断路器恢复到一个关闭状态,并允许流量进入。否则,它就会打开。


image.png


*测试失败 Testing for Failures


你应该不断地测试你的系统以防止常见问题,以确保你的服务能够承受住各种失败。你应该频繁地测试失败,让你的团队为发生事故而做好准备。


对于测试,你可以使用一个外部服务来标识实例组,并随机终止该组中的一个实例。有了这个,你就可以为单个实例的失败做准备,你甚至可以关闭整个可用区来模拟云提供商的中断。


最流行的测试解决方案之一是由Netflix提供的ChaosMonkey弹性工具。


*结尾


实现和运行可靠的服务并不容易。这需要你付出很大的努力,也要花费你的公司很多钱。


可靠性有很多的层次和方面,所以为你的团队找到最好的解决方案是很重要的。你应该将可靠性作为业务决策过程中的一个因素,并为它分配足够的预算和时间。


*主要收获


动态环境和分布式系统——比如微服务——会导致更大的失败机率。 服务应该单独失败,实现优雅的降级,用以改善用户体验。 70%的中断是由变更引起的,恢复代码并不是件坏事。 快速和独立的失败。团队无法控制他们服务的依赖。 架构模式和技术,如缓存、舱壁、限流、熔断,有助于建立可靠的微服务。


原文:https://blog.risingstack.com/designing-microservices-architecture-for-failure/

译文:https://blog.csdn.net/xushuai110/article/details/77726447


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
2月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
5月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
291 0
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
358 3
|
机器学习/深度学习 自然语言处理 分布式计算
大规模语言模型与生成模型:技术原理、架构与应用
本文深入探讨了大规模语言模型(LLMs)和生成模型的技术原理、经典架构及应用。介绍了LLMs的关键特点,如海量数据训练、深层架构和自监督学习,以及常见模型如GPT、BERT和T5。同时,文章详细解析了生成模型的工作原理,包括自回归模型、自编码器和GANs,并讨论了这些模型在自然语言生成、机器翻译、对话系统和数据增强等领域的应用。最后,文章展望了未来的发展趋势,如模型压缩、跨模态生成和多语言多任务学习。
1932 3
|
8月前
|
监控 NoSQL 算法
百万级URL重定向工程:大规模网站架构设计与性能优化实战
本文深入探讨了大规模重定向系统的核心挑战与解决方案,涵盖技术瓶颈分析、分布式架构设计、十亿级URL处理策略、全球化部署方案及全链路监控体系。通过数学建模与性能优化,提出三层架构模型,并结合一致性哈希分片算法实现高效路由。同时,对比不同架构的吞吐量与容灾能力,分享某电商平台实践案例,展示性能显著提升。最后展望重定向即服务(RaaS)未来趋势,包括AI动态路由、量子安全跳转和边缘智能等关键技术,为企业提供扩展性强、稳定性高的系统设计参考。
335 25
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
1052 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
8月前
|
Cloud Native Serverless 流计算
云原生时代的应用架构演进:从微服务到 Serverless 的阿里云实践
云原生技术正重塑企业数字化转型路径。阿里云作为亚太领先云服务商,提供完整云原生产品矩阵:容器服务ACK优化启动速度与镜像分发效率;MSE微服务引擎保障高可用性;ASM服务网格降低资源消耗;函数计算FC突破冷启动瓶颈;SAE重新定义PaaS边界;PolarDB数据库实现存储计算分离;DataWorks简化数据湖构建;Flink实时计算助力风控系统。这些技术已在多行业落地,推动效率提升与商业模式创新,助力企业在数字化浪潮中占据先机。
473 12
|
10月前
|
机器学习/深度学习 缓存 自然语言处理
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构
DeepSeekMoE是一种创新的大规模语言模型架构,融合了专家混合系统(MoE)、多头潜在注意力机制(MLA)和RMSNorm归一化。通过专家共享、动态路由和潜在变量缓存技术,DeepSeekMoE在保持性能的同时,将计算开销降低了40%,显著提升了训练和推理效率。该模型在语言建模、机器翻译和长文本处理等任务中表现出色,具备广泛的应用前景,特别是在计算资源受限的场景下。
1328 29
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构

热门文章

最新文章