如何处理瞬时故障?
在服务网格中使用 Envoy 的最大优势之一是,它使服务免于实现复杂的弹性功能,例如断路器、异常检测和重试,这些功能使服务能够应对滚动升级、动态基础设施和网络故障等现实情况。在 Envoy 中实现这些功能不仅提高了服务的可用性和弹性,而且在行为和可观察性方面带来了一致性。
本节将从高层面上解释 Envoy 支持的配置以及如何将这些功能一起使用来处理这些情况。
断路器
断路器 是分布式系统的重要组成部分。断路器允许应用程序配置故障阈值,以确保安全的最大值,使组件能够快速失败并尽快施加反压。应用正确的断路器阈值有助于节省资源,否则这些资源将浪费在等待请求(超时)或不必要地重试请求上。Envoy 中断路器实现的主要优势之一是断路器限制是在网络层应用的。
重试
自动 请求重试 是确保服务弹性的另一种方法。请求重试通常应该用于防止瞬时故障。Envoy 支持非常丰富的可配置参数集,这些参数决定了哪些类型的请求将被重试,请求应该被重试多少次,重试的超时时间等。
gRPC 服务中的重试
对于 gRPC 服务,Envoy 会查看响应中的 gRPC 状态,并根据 x-envoy-retry-grpc-on 中配置的状态尝试重试。
以下 gRPC 中的应用程序状态代码被认为是自动重试安全的。
CANCELLED - 如果服务中存在可以重试的错误,则返回此代码。
RESOURCE_EXHAUSTED - 如果服务依赖的一些资源在该实例中耗尽,因此重试到另一个实例将有所帮助,则返回此代码。请注意,对于共享资源耗尽,返回此代码将无济于事。相反,应该使用 速率限制 来处理此类情况。
HTTP 状态代码 502 (Bad Gateway)、503 (Service Unavailable) 和 504 (Gateway Timeout) 都映射到 gRPC 状态代码 UNAVAILABLE。这也可以被认为是自动重试安全的。
请求的幂等性是配置重试时需要考虑的重要因素。
Envoy 还支持其重试策略的扩展。 重试插件 允许您根据您的应用程序自定义 Envoy 重试实现。
异常检测
异常检测 是一种动态检测上游集群中行为异常主机的机制。通过检测此类主机并将它们从健康的负载均衡集中临时弹出,Envoy 可以提高集群的成功率。Envoy 支持基于连续 5xx、连续网关故障和成功率配置异常检测。
Envoy 还允许您配置弹出周期。
配置
以下设置有助于优化以下几种情况的组合
常见场景(例如滚动升级)的最大请求成功率
速度
避免级联故障
断路器
{
"thresholds": [
{
"max_retries": 10,
}
]
}
出于此特定用例的目的,应该配置上游集群的重试预算以启用和控制并发重试。如果配置的值过低,则某些请求将不会被重试,这可以通过 upstream_rq_retry_overflow 进行测量。如果配置的值过高,服务可能会被重试请求淹没。
异常检测
{
"consecutive_5xx": 5,
"base_ejection_time": "30s",
"max_ejection_percent": 50,
"consecutive_gateway_failure": 5,
}
此设置在出现 5 个连续 5xx 或 网关故障 时启用异常检测,并将弹出的主机数量限制为上游集群大小的 50%。此配置对被移除的主机数量设置了安全限制。请注意,一旦主机被弹出,它将在弹出时间过后返回池(等于 base_ejection_time 乘以主机被弹出的次数)。
请求重试
{
"retry_on": "cancelled,connect-failure,gateway-error,refused-stream,reset,reset-before-request,resource-exhausted,unavailable",
"num_retries": 1,
"retry_host_predicate": [
{
"name": "envoy.retry_host_predicates.previous_hosts"
}
],
"host_selection_retry_max_attempts": "5"
}
将根据 retry_on 中记录的条件重试请求。此设置还配置 Envoy 使用 先前主机重试谓词,它允许 Envoy 选择与先前请求失败的主机不同的主机,因为通常情况下,同一主机的故障很可能持续一段时间,而立即重试成功的可能性较小。