Kong健康检查&熔断器向导
简介
用户可以使用Kong的 ring-balancer 配置 API 代理,ring-balancer 会在多个 target 之间实现负载均衡,并基于 upstream 配置对每个 target 进行健康检查,针对它们是否正常响应判定它们是否健康,之后 ring-balancer 仅会将流量路由到健康的 target,Kong支持两种健康检查,可以单独使用,也可以结合使用:
- 主动检查:定期检查 target 中指定的 Http 或 Https 端点,并根据其响应确定 target 的运行状况
- 被动检查:也称为断路器,Kong会分析正在运行的代理流量,并根据其响应请求行为确定 target 的运行状况
健康与不健康的 target
健康检查的目的是对于一个指定的Kong节点,可以动态的标记其下的 target 是否健康,集群范围内不会同步健康信息,每个Kong节点单独判断 target 的健康情况,这种做法是可取的,因为在一个时间点,一个Kong节点可能可以成功连接到某个 target,但是另一个Kong节点连接失败,这样第一个节点就标记其为健康,另一个标记为不健康,并且不再将流量路由到此处
活动探测(主动健康检查)或者代理请求(被动健康检查)都会生成用于确定 target 健康与否的数据,请求可能会导致 TCP 错误,超时,或者生成一个 Http 状态码,基于这些数据,健康检查器会更新一系列内部计数器:
- 如果返回的状态码配置为健康,那么它会累加
成功
计数器,并清空其他所有计数器 - 如果连接失败,那么它会累加
TCP 失败
计数器,并清空所有成功
计数器 - 如果超时,那么它会累加
超时
计数器,并清空所有成功
计数器 - 如果返回的状态码配置为不健康,那么它会累加
HTTP 失败
计数器,并清空所有成功
计数器
如果TCP 失败
、超时
或HTTP 失败
计数器中的任何一个达到它们配置的阈值,target 就会标记为不健康;如果成功
计数器达到它配置的阈值,target 就会标记为健康
每个 upstream 可以配置标记健康与否的 HTTP 状态列表和每个计数器的阈值,下面我们有一份 upstream 实体的配置示例,展示了健康检查配置项的默认值,详细信息可以参考 Admin API 的参考文档
{
"name": "service.v1.xyz",
"healthchecks": {
"active": {
"concurrency": 10,
"healthy": {
"http_statuses": [ 200, 302 ],
"interval": 0,
"successes": 0
},
"http_path": "/",
"timeout": 1,
"unhealthy": {
"http_failures": 0,
"http_statuses": [ 429, 404, 500, 501,
502, 503, 504, 505 ],
"interval": 0,
"tcp_failures": 0,
"timeouts": 0
}
},
"passive": {
"healthy": {
"http_statuses": [ 200, 201, 202, 203,
204, 205, 206, 207,
208, 226, 300, 301,
302, 303, 304, 305,
306, 307, 308 ],
"successes": 0
},
"unhealthy": {
"http_failures": 0,
"http_statuses": [ 429, 500, 503 ],
"tcp_failures": 0,
"timeouts": 0
}
}
},
"slots": 10
}
如果 upstream 下的所有 target 都不健康,那么Kong会返回 503 Service Unavailable
注意:
- 健康检查仅作用于活动状态的 target,但是不修改Kong数据库中 target 的活动状态
- 不健康的 target 不会从负载均衡器中移除,因此在使用Hash算法时,不会对平衡器布局造成任何影响(它们只是被跳过)
- DNS 和 平衡器的注意事项也适用于健康检查,如果 target 使用主机名,要确保 DNS 服务器始终返回完整的 IP 地址集,并且不限制响应,如果不这样做会健康检查无法执行
健康检查类型
主动健康检查
顾名思义,主动健康检查会积极查询健康状态,当 upstream 中启用主动健康检查时,Kong会向每个 target 的固定路径周期性地发送 Http 或者 Https 请求,这使得Kong可以根据探测结果自动启用或禁用平衡器中的 target
Kong可以根据 target 健康与否单独配置健康检查的周期,如果其中的一个间隔时间设置为0,那么在对应中的场景中会禁用检查;如果两个都设为0,将完全禁用主动健康检查
被动健康检查(断路器)
被动健康检查,即断路器,是根据Kong代理的请求执行检查,它本身不会产生额外流量,当 target 无响应时,被动检查器会检测到,并将其标记为不健康,ring-balancer 会跳过这个 target,不会将流量路由到这个 target,当问题解决了之后并且准备好再次接受流量时,Kong管理员可以手动触发请求,使健康检查器重新检测该 target
curl -i -X POST http://localhost:8001/upstreams/my_upstream/targets/10.1.2.3:1234/healthy HTTP/1.1
204 No Content
此命令将在集群范围内广播消息,所以健康
状态会传播到整个Kong集群,这会导致所有Kong节点都会重置健康检查器的健康计数器,从而允许 ring-balancer 能够再次将流量路由到该 target,被动健康检查的优点是不会产生额外的流量,但是它们无法再次自动将 target 标记为健康,断路器需要系统管理员重新激活
两类健康检查器总结
- 主动健康检查器可以在 target 恢复健康之后自动恢复流量;但是被动健康检查器不能
- 被动健康检查器不会产生额外的流量;主动健康检查器会
- 主动健康检查器需要一条URL路径可以访问,作为探测的端点(通常简单配置为"/");被动检查器不需要这样的配置
- 应用可以根据自身的健康指标生成一个状态码,提供给主动健康检查器,这样即使 target 还能持续提供给被动健康检查器流量,同时也能响应主动健康检查器的错误状态
用户可以组合使用者两种模式,例如使用被动检查器仅根据流量状态监控该 target 健康与否,再仅在非健康状态情况下使用主动检查器,以便自动重启该 target
启用、停用健康检查
启用主动健康检查
要启用主动健康检查,用户需要在 upstream 对象中配置 healthchecks.active
属性的值,指定一些必要的信息,这样Kong可以对 target 执行定期探测,并对结果做出反应
用户可以使用 healthchecks.active.type
字段来指定是用 HTTP
还是 HTTPS
探测,或者可以设置成 TCP
简单地测试给定的地址和端口是否可以连接
用户配置探针时,需要指定以下字段:
-
healthchecks.active.http_path
:向 target 发出 Http Get 请求的地址,默认是"/" -
healthchecks.active.timeout
:Http Get 请求的连接超时时间,默认是1秒 -
healthchecks.active.concurrency
:主动检查时 target 的并发数
用户需要将间隔时间设置为正值以便运行探针: -
healthchecks.active.healthy.interval
:健康 target 的检查间隔时间(以秒为单位),值为0表示对健康的 target 不执行健康检查 -
healthchecks.active.unhealthy.interval
:非健康 target 的检查间隔时间(以秒为单位),值为0表示对非健康的 target 不执行健康检查
用户可以调整健康检查的行为,用户可以将健康与非健康的 target 的检查间隔时间设成一致,也可以一个比另一个更频繁一些
当用户使用 HTTPS 健康检查时,还可以指定以下字段: -
healthchecks.active.https_verify_certificate
:检查时是否检查远程主机的SSL证书的有效性 -
healthchecks.active.https_sni
:SNI 的主机名,当使用 IP 配置 target 时尤其有效
注意,TLS验证的错误将累计在 TCP 失败计数器上,HTTP 失败次数仅针对 HTTP 状态码,无论是通过 HTTP 协议还是 HTTPS 协议
最后,用户需要配置各种健康计数器的阈值,告知Kong如何解析这些探测: -
healthchecks.active.healthy.successes
:HTTP状态成功次数的阈值 -
healthchecks.active.unhealthy.tcp_failures
:TCP失败或者TLS验证失败次数的阈值 -
healthchecks.active.unhealthy.timeouts
:超时次数的阈值 -
healthchecks.active.unhealthy.http_failures
:HTTP状态失败次数的阈值
启用被动健康检查
被动健康检查没有探测功能,它通过流经 target 的流量来工作,这意味启动被动检查,用户只需要配置计数器阈值:
-
healthchecks.passive.healthy.successes
:HTTP状态成功次数的阈值,这个值需要设置为正值 -
healthchecks.passive.unhealthy.tcp_failures
:TCP失败计数器 -
healthchecks.passive.unhealthy.timeouts
:超时次数阈值 -
healthchecks.passive.unhealthy.http_failures
:HTTP状态失败次数的阈值
停用健康检查
被动健康检查没有探测功能,它通过流经 target 的流量来工作,这意味启动被动检查,用户只需要配置计数器阈值:
-
healthchecks.passive.healthy.successes
:HTTP状态成功次数的阈值,这个值需要设置为正值,这样健康的流量可以重置非健康计数器 -
healthchecks.passive.unhealthy.tcp_failures
:TCP失败计数器 -
healthchecks.passive.unhealthy.timeouts
:超时次数阈值 -
healthchecks.passive.unhealthy.http_failures
:HTTP状态失败次数的阈值
停用健康检查
对于健康检查中所有的阈值和间隔,将它们设置为0,就可以禁用该属性表示的功能,将探测的间隔时间设为0可以禁用该探测,这样用户可以对健康检查程序的行为进行细粒度的控制
总结起来,禁用主动健康检查,需要将 healthchecks.active.healthy.interval
和 healthchecks.active.unhealthy.interval
这两个参数都设为0;禁用被动健康检查,需要将被动健康检查的阈值都设置为0
默认情况下,健康检查器中的所有阈值和时间间隔默认值都为0,这意味着新创建的 upstream 默认情况下是完全禁用健康检查的