Istio从入门到精通—— 流量治理的原理 —— 服务容错

 流量治理的原理 —— 容错策略 —— 故障转移、快速失败、安全失败、沉默失败、故障恢复并行调用、广播调用

  在分布式系统架构中,容错机制是一个至关重要的组成部分。由于分布式系统的本质是不可靠的,一个大的服务集群中可能会发生各种“意外情况”,例如程序崩溃、节点宕机、网络中断等。为了应对这些意外情况,我们需要采取一系列的容错策略和设计模式来确保系统的稳定性和可用性。

  容错策略:故障时,我们的应对措施。

  容错设计模式如何实施这些措施的具体方法。

一、故障转移(Failover)

    故障转移(Failover)是系统韧性设计中的一个基础能力,一般表示在服务器、系统、硬件或网络发生故障不能服务服务时切换到备用的系统,自动无缝完成故障检测和切换,减少或消除对使用方或最终用户的影响,从而提高整个系统对外的可用性。

  故障转移(Failover)是指如果调用的服务器出现故障,系统不会立即向调用者返回失败结果,而是自动切换到其他服务副本,尝试其他副本能否返回成功调用的结果,从而保证了整体的高可用性。

二、快速失败(Failfast)

  对于非幂等的服务,实施故障转移策略可能会导致脏数据和其他问题在这些情况下,快速失败是一个更为安全和可靠的容错策略。以下是需要采用快速失败策略的业务场景:

2.1、支付场景

2.1.1、场景描述

  在电子商务或在线服务中,用户支付是一个关键步骤。通常,支付过程会涉及调用第三方支付网关或银行的接口来完成扣款操作。

2.1.2、问题分析

  如果扣款接口返回网络异常,很难判断是发送扣款指令时出现问题,还是银行扣款后返回结果时出现问题。重复调用扣款接口可能会导致重复扣款,给用户带来经济损失,同时也会引发用户的不满和投诉。

2.1.3、容错策略

  为了避免重复扣款,最恰当的策略是在接口调用失败时立即报错,不进行重试。
  快速失败策略可以确保问题被及时发现和处理,而不是隐藏起来导致更大的麻烦。调用者(通常是上游服务或应用)可以根据错误信息进行相应的处理,例如通知用户支付失败,或者提供其他支付方式。

2.2、订单场景

2.2.1、场景描述

  在电商或零售系统中,订单确认是一个重要环节。当用户下单后,系统需要确认订单信息并更新库存、账户余额等。

2.2.2、问题分析

  订单确认操作通常不是幂等的,重复确认可能会导致库存不准确、用户多扣费等问题。如果订单确认接口调用失败,重试可能会导致重复确认,从而产生脏数据。

2.2.3、容错策略

  为了确保数据的一致性,当订单确认接口调用失败时,应该立即报错,不进行重试。快速失败策略可以让问题及时暴露出来,由上游服务或应用根据错误信息进行相应的处理,例如通知用户订单确认失败、回滚已扣费用等。

2.3、文件处理场景

2.2.1、场景描述

  在很多应用中,文件上传、下载和处理是常见的功能。例如,用户上传头像、文档等。

2.2.2、问题分析

  文件处理操作通常不是幂等的。如果文件上传或处理失败,重试可能会导致重复的文件被创建或处理,从而浪费存储空间或产生不一致的结果。

2.2.3、容错策略

  为了确保文件的一致性和准确性,当文件处理接口调用失败时,应该立即报错,不进行重试。调用者可以根据错误信息进行相应的处理,例如通知用户上传失败、删除已上传的重复文件等。

2.4、在线投票系统

2.4.1、场景描述

  在一个在线投票系统中,用户可以对不同的选项进行投票。系统需要实时统计并显示各选项的得票数。

2.4.2、问题分析

  在在线投票系统中,投票操作具有非幂等性。如果用户对一个选项重复投票,会导致该选项的得票数不准确。此外,实时统计和显示得票数也需要确保数据的实时性和准确性。如果在统计或显示过程中出现故障,重试可能会导致数据重复统计或显示错误,从而影响投票结果的公正性和准确性。

2.4.3、容错策略

  为了确保投票结果的准确性和公正性,当投票系统出现故障时,应该立即报错,不进行重试。快速失败策略可以确保问题被及时发现和处理,而不是隐藏起来导致更大的麻烦。同时,系统可以提供相应的错误提示信息,引导用户重新进行投票或等待系统恢复正常。调用者(通常是上游服务或应用)也可以根据错误信息进行相应的处理,例如记录错误日志、通知管理员等。这样可以确保投票系统的稳定性和数据的准确性。

三、安全失败(Failsafe)

  安全失败策略是一种容错策略,用于处理那些即使失败也不会影响核心业务流程的服务调用。

  下面将列举三个应用场景,并从场景描述、场景分析和容错策略三个方面进行详细分析:

3.1、在线电商的日志记录服务场景

3.1.1、场景描述

  在一个在线电商系统中,当用户下单时,需要记录用户的操作日志。日志记录服务是一个旁路服务,即使它失败了,用户的下单操作依然需要成功。

3.1.2、场景分析

  日志记录服务属于旁路逻辑,因为后续处理(如下单操作)并不依赖其返回值。它的主要作用是为了审计和跟踪,如果调用失败,不应该影响主业务流程。

3.1.3、容错策略

  可以采用安全失败策略。当调用日志记录服务失败时,返回一个空值或者默认值,并记录一条服务调用出错的日志备查。这样,即使日志记录服务出现问题,用户的下单操作也不会受到影响。

3.2、实时推荐系统的非关键推荐服务

3.2.1、场景描述

  在一个实时推荐系统中,根据用户的行为和喜好,系统会推荐相关的内容。其中有一个非关键的推荐服务,它提供的是一些次要的、不那么重要的推荐信息。

3.2.2、场景分析

  这个非关键的推荐服务属于旁路逻辑,因为即使它失败了,核心的推荐功能依然需要正常工作。它的返回值对最终推荐结果的影响不大。

3.2.3、容错策略

  可以使用安全失败策略。如果调用这个非关键的推荐服务失败,系统可以返回一个预设的默认推荐列表,并记录错误日志备查。这样,用户可以仍然获得一些推荐内容,而系统也可以在后台修复这个问题。

四、沉默失败(Failsilent)

  如果大量的请求需要等到超时(或者长时间处理后)才宣告失败很容易由于某个远程服务的请求堆积而消耗大量的线程、内存、网络等资源,进而影响到整个系统的稳定。面对这种情况,一种合理的失败策略是当请求失败后,就默认服务提供者一定时间内无法再对外提供服务,不再向它分配请求流量,将错误隔离开来,避免对系统其他部分产生影响,此即为沉默失败策略。

五、故障恢复(Failback)

  故障恢复一般不单独存在,而是作为其他容错策略的补充措施。

  一般在微服务管理框架中,如果设置容错策略为故障恢复的话,通常默认会采用快速失败加上故障恢复的策略组合。它是指当服务调用出错了以后,将该次调用失败的信息存入一个消息队列中,然后由系统自动开始异步重试调用。

  故障恢复策略一方面是尽力促使失败的调用最终能够被正常执行,另一方面也可以为服务注册中心和负载均衡器及时提供服务恢复的通知信息。

  故障恢复显然也是要求服务必须具备幂等性的由于它的重试是后台异步进行,即使最后调用成功了,原来的请求也早已经响应完毕,所以故障恢复策略一般用于对实时性要求不高的主路逻辑,同时也适合处理那些不需要返回值的旁路逻辑。为了避免在内存中异步调用任务堆积,故障恢复与故障转移一样,应该有最大重试次数的限制。

六、并行调用(Forking)

  上面五种以“Fail”开头的策略是针对调用失败时如何进行弥补的,以下这两种策略则是在调用之前就开始考虑如何获得最大的成功概率。

  并行调用策略很符合人们日常对一些重要环节进行的“双重保险”或者“多重保险”的处理思路,它是指一开始就同时向多个服务副本发起调用,只要有其中任何一个返回成功,那调用便宣告成功。这是一种在关键场景中使用更高的执行成本换取执行时间和成功概率的策略。

七、广播调用(Broadcast)

  广播调用与并行调用是相对应的,都是同时发起多个调用并行调用是任何一个调用结果返回成功便宣告成功,广播调用则是要求所有的请求全部都成功,这次调用才算是成功,任何一个服务提供者出现异常都算调用失败。广播调用通常会被用于实现“刷新分布式缓存”这类的操作

八、常见容错策略优缺点及应用场景对比

九、基于 Kubernetes 的故障转移

  基于Kubernetes的故障转移策略可以通过跨可用区部署、多集群部署、Pod反亲和性、就绪探针和存活探针、自动扩展以及数据持久化等技术手段实现。这些策略可以根据具体的业务场景和需求进行灵活组合和配置,以提高业务的可用性和弹性。

  1. 跨可用区(Availability Zone)部署: 为了降低整个集群因单一可用区故障而受影响的风险,我们推荐将Kubernetes集群部署在多个可用区中。这种跨可用区的部署策略能确保在某一可用区发生故障时,业务可以自动、迅速地转移到其他正常运行的可用区,从而实现高效的故障转移。
  2. 多集群部署: 为了进一步提高业务的可用性,可以在不同的地域或云服务商处部署多个Kubernetes集群。通过多集群部署,当一个集群发生故障时,可以将业务自动转移到其他集群上,实现跨地域或跨云服务商的故障转移。
  3. Pod反亲和性(Pod Anti-Affinity): 通过定义Pod反亲和性规则,可以确保同一业务的不同Pod实例不会部署在同一个节点上。这样,当某个节点发生故障时,该节点上的所有Pod实例都会转移到其他节点上,避免了单点故障。
  4. 自动扩展(Auto-scaling): 通过自动扩展功能,可以根据业务的负载情况动态调整Pod的数量。当某个Pod发生故障时,自动扩展功能会自动增加健康的Pod实例,以保证业务的处理能力不受影响。
  5. 数据持久化: 对于需要持久化存储的业务,可以使用Kubernetes的存储卷(Volume)和持久存储卷(Persistent Volume)功能。通过将数据存储在持久存储卷中,并在多个节点之间共享存储卷,可以在节点发生故障时保证数据的完整性和可用性。

十、基于 Istio 的故障转移

    Isito 是一种广泛使用的服务网格平台,提供了众多功能,其中包括故障转移,以确保在部分区域或节点发生故障时,业务能够自动、迅速地转移到其他正常运行区域或节点。下面是关于 Isito 在故障转移中的工作原理及流程的详细教程。

10.1、Istio故障转移概述

  Isito 的故障转移是通过 Kubernetes 来实现的,它允许在多个区域或可用区(Availability Zone,AZ)之间进行自动故障转移。这种机制基于 Isito 的自动服务发现和负载均衡功能,可以确保在部分区域发生故障时,流量能够被重新路由到其他正常运行的区域或节点。

10.2、工作原理

    1. 服务发现和负载均衡: Isito通过Kubernetes的API进行服务发现和负载均衡。当服务启动时,Isito会将其注册到Kubernetes的Service中,并通过Envoy进行转发。这样,Isito能够实时地了解所有运行中的服务和节点。
    2. 健康检查: Isito通过Kubernetes的健康检查机制来确定节点的状态。如果某个节点或区域出现故障,健康检查会返回失败,Isito将不再将流量发送到该节点或区域。
    3. 流量重定向: 当Isito检测到某个节点或区域出现故障时,它会通过修改Kubernetes的Service定义来实现流量的重定向。具体来说,Isito会修改Service的Endpoint,将故障节点或区域的IP地址替换为其他正常节点的IP地址。
    4. 动态服务网格: Isito的动态服务网格特性允许其在不影响现有服务的情况下进行自动配置和调整。这意味着,即使在部分区域发生故障时,Isito也可以动态地调整流量路由,以确保业务连续性。

10.3、使用 Istio 进行故障转移的步骤

    1. 配置Isito: 首先,需要配置Isito以使其能够与Kubernetes进行通信。这涉及到设置 Kubernetes 的 kubeconfig 文件,以允许Isito访问Kubernetes集群中的资源。
    2. 创建Kubernetes Service: 在Kubernetes中创建一个Service以暴露你的应用程序的服务。在这个Service中,你需要指定一个或多个端口号,以及运行应用程序的Pod的标签选择器。
    3. 配置Isito进行流量路由: 在Isito的配置文件中,你需要指定从哪个端口接收流量,并将流量路由到哪个Kubernetes Service。你可以使用Isito的Helm chart或直接编辑Isito的yaml配置文件来完成这个步骤。
    4. 启动Isito: 启动Isito代理以开始接收和转发流量。你可以通过修改Isito的yaml配置文件中的端口号来监听特定的端口。
    5. 测试故障转移: 为了测试故障转移功能,你可以尝试模拟节点或区域故障。例如,你可以关闭一个节点或区域,并观察Isito是否将流量重定向到其他正常运行节点或区域。
    6. 监控和管理: 使用Isito和Kubernetes提供的监控和管理工具来监控和管理你的应用程序和服务。你可以使用Kubernetes仪表板、Isito仪表板或其他监控工具来实时查看流量路由、节点状态等信息。
    7. 启动Isito: 启动Isito代理以开始接收和转发流量。你可以通过修改Isito的yaml配置文件中的端口号来监听特定的端口。
    8. 持续优化: 根据监控数据和业务需求,持续优化Isito的配置和流量路由策略。这可能包括添加更多节点或区域、调整负载均衡策略、优化服务网格等。

    在 Istio 中可以以非侵入的方式实现以上故障转移过程,在控制面配置故障转移策略,服务网格数据面拦截到源服务对目标服务的请求时,在转发请求的过程中根据故障转移策略将流量转移到配置的服务实例。

    比如,可以在配置 region1 的实例不可用时,优先将流量转移到 region2 的服务实例。

posted @ 2023-11-29 17:57  左扬  阅读(301)  评论(0编辑  收藏  举报
levels of contents