在单体应用程序中,一个错误就有可能导致整个应用程序崩溃。在微服务架构中可以避免这种情况,因为它包含较小的独立可部署单元,这不会影响整个系统。但这是否意味着微服务架构能够抵御故障?一点都不。将整体应用程序转换为微服务并不能自动解决问题。事实上,使用分布式系统有其自身的挑战!
在构建分布式云应用程序时,您应该假设会发生故障并设计具有弹性的应用程序。微服务生态系统总会在某个时候失败,因此您需要接受失败。不要假设系统会全年顺利进行来设计系统。现实一点,考虑到下雨、下雪、雷暴和其他不利条件的可能性(如果我可以用比喻的话)。简而言之,设计微服务时要考虑到失败。事情并不总是按计划进行,您需要为最坏的情况做好准备。
如果服务 A 调用服务 B,服务 B 又调用服务 C,那么当服务 B 宕机时会发生什么?在这种情况下,您的后备计划是什么?
能否向用户返回预先确定的错误消息?
您可以调用其他服务来获取信息吗?
您可以从缓存中返回值吗?
可以返回默认值吗?
您可以采取多种措施来确保整个微服务链不会因单个组件的故障而失败。
微服务架构中可能会出现什么问题?
微服务架构中有许多移动组件,因此存在更多的故障点。失败可能由多种原因引起------代码中的错误和异常、新代码的发布、部署不当、硬件故障、数据中心故障、架构不佳、缺乏单元测试、通过不可靠的网络进行通信、依赖服务等。
为什么需要使服务具有弹性?
分布式应用程序的一个问题是它们通过网络进行通信------这是不可靠的。因此,您需要设计微服务,使其能够容错并优雅地处理故障。在您的微服务架构中,可能有十几个服务相互通信。您需要确保一项失败的服务不会导致整个架构瘫痪。
如何使您的服务具有弹性?
识别故障场景
在将新的微服务发布到生产环境之前,请确保您已经对其进行了足够好的测试。但奇怪的事情可能会发生,你应该为最坏的情况做好准备。这意味着您应该准备好在短时间内从各种故障中优雅地恢复。这使人们对系统承受故障并以最小影响快速恢复的能力充满信心。因此,识别架构中的故障场景非常重要。
实现此目标的一种方法是让微服务发生故障,然后尝试从故障中恢复。这个过程通常称为混沌测试。考虑如下场景并了解系统的行为方式:
服务 A 无法与服务 B 通信。
数据库无法访问。
您的应用程序无法连接到文件系统。
服务器已关闭或没有响应。
将故障/延迟注入服务中。
避免级联故障
当您在架构内构建了服务依赖项时,您需要确保一项失败的服务不会在整个链中造成连锁反应。通过避免级联故障,您将能够节省网络资源、充分利用线程并允许故障服务恢复!
简而言之------不要用额外的请求来打击已经关闭的服务。请给服务时间来恢复。
避免单点故障
在设计微服务时,考虑一下当特定组件发生故障时微服务将如何表现总是一件好事。这将带来更健康的讨论,并有助于构建容错服务。
但请确保不要以一种服务极大依赖于单个组件的方式进行设计。如果发生这种情况,请确保制定从故障中快速恢复的策略。
设计应用程序时不要出现单点故障。您应该能够随时处理客户请求。因此,确保整个微服务生态系统的可用性至关重要。
优雅地处理故障并允许快速降级
您应该设计微服务,使其具有容错能力 - 如果出现错误/异常,服务应该通过提供错误消息或默认值来优雅地处理它。您的微服务需要具有容错能力并优雅地处理故障。
为失败而设计
通过遵循一些常用的设计模式,您可以使您的服务实现自我修复。现在让我们详细讨论这些设计模式。
确保服务弹性的设计模式是什么?
断路器模式
如果您的微服务生态系统出现故障,那么您需要通过打开电路来快速失败。这可以确保一旦断路器打开,就不会再对失败的服务进行任何调用。所以我们立即返回异常。此模式还监视系统是否出现故障,一旦一切恢复正常,电路就会关闭以允许正常功能。
断路器设计模式
这是避免微服务生态系统中出现级联故障的一种非常常见的模式。
您可以使用一些流行的第三方库在应用程序中实现熔断,例如 Polly 和 Hystrix。
Polly-标志-1
海斯特里克斯
重试设计模式
此模式表明您可以自动重试先前由于异常而失败的连接。如果您的一项服务出现临时问题,这非常方便。很多时候,简单的重试就可以解决问题。负载均衡器可能会在重试时将您指向不同的运行状况良好的服务器,并且您的调用可能会成功。
超时设计模式
此模式指出您不应无限期地等待服务响应 --- 抛出异常而不是等待太长时间。这将确保您不会陷入困境,继续消耗应用程序资源。一旦达到超时时间,线程就会被释放。