英文原文:https://getkong.org/docs/0.11.x/clustering/
第一次翻译,难免有翻译偏差,望各位见谅。转载请署名,谢谢!
kong 集群将使得系统通过增加更多机器,从而实现水平扩展,承接更多的请求流量。它们将共享同样的配置且使用同一个数据库。kong 集群中的的所有节点都连接同一个数据库。
你需要在 kong 集群的上一层架设一个负载均衡的代理服务器,以便请求能够平均分散转发到 kong 的各个节点上。
当搭建好一个 kong 集群并不意味着客户端请求将会负载均衡到 kong 集群中的每个节点上,kong 集群并不是开箱即用,你仍然需要在 kong 集群多节点上层搭建负载均衡,以便分发请求。 一个 kong 集群只是意味着集群内的节点,都共享同样的配置。
考虑到性能原因,当 kong 代理请求的时候,为了避免频繁的数据库连接操作,kong 将会把以下 db 内容缓存到本机内存中。这些缓存包括:API定义,用户信息,插件信息,授权认证信息等。由于这些值在本机缓存中,通过 Admin api 去更新任何一个节点本地缓存中的值,都需要传播给其他节点。
本文档将介绍,如何使得这些本地缓存失效,并且如何配置 kong 集群节点,以便支持更多的使用场景,从而在性能和数据强一致性两方面做出平衡的选择。
只有一个 kong 节点连接数据库的单节点 kong 集群,任何通过 Admin api 的更改,都会立即全局生效。比如:
假设只有一个单节点 kong-A ,如果我们删除一个已经注册的API:
$ curl -X DELETE http://127.0.0.1:8001/apis/test-api
随后任何关于 kong-A test-api 的请求都将会返回 “404 Not Found”,因为该节点已经在本地删除中清除了缓存。
$ curl -i http://127.0.0.1:8000/test-api
在一个多节点 kong 集群中,当我们通过A 节点的Admin api删除某条信息,其他节点虽然都连接同一个数据库,但由于本地缓存存在,所以并不会立即生效。虽然API 不再存储在数据库中(通过A 节点的Admin api 删除的),但它仍然存在 B以及其他节点的内存中。
所有节点将会周期性执行后台同步任务,同步其他节点触发的变化。该同步任务执行频率可以通过配置下面的配置项:
◦ db_update_frequency (默认: 5 秒)
每 db_update_frequency 秒,所有 kong 节点将从数据库中拉取所有更新,如果有同步到更新变化,将清理本地相关缓存。
如果我们通过 kong-A 节点删除一个 API,这个更新变化将不会立即在 B 节点生效,直到 B 节点下一次从数据库拉取变更,这将会是在db_update_frequency 秒后才会发生(也有肯能会更早)。
这个过程将会使 kong 集群最终保持一致性。
所有的核心实体比如:接口信息,插件信息,用户信息,授权认证信息均被缓存在本地内存中,缓存失效则依赖后台任务同步更新。
此外,kong 也会缓存数据库遗漏(数据库中有的数据,但本地不存在的),那就意味着你通过 admin-api 配置了一个 API 没有配置插件,kong 将会缓存这个信息。 例如:
关于节点 A, 我们增加一个 API :
# node A
$ curl -X POST http://127.0.0.1:8001/apis \
--data "name=example" \
--data "upstream_url=http://example.com" \
--data "uris=example"
当请求到达 A 和 B,节点都会缓存这个API信息,原因是因为这个 API 没有配置任何插件。
# node A
$ curl http://127.0.0.1:8000/example
HTTP 200 OK
...
# node B
$ curl http://127.0.0.2:8000/example
HTTP 200 OK
...
现在,假如我们通过 kong-A 节点为该 API 增加一个插件:
# node A
$ curl -X POST http://127.0.0.1:8001/apis/example/plugins \
--data "name=example-plugin"
因为该请求是通过 kong-A admin api 处理的,节点 kong-A 将会使它本地缓存无效,对于后续过来的请求,将会发现这个API 已经配置了插件,并且后续请求到节点 kong-A 的请求,都将要经过插件处理。
无论如何,kong-B 节点还没有执行数据库同步更新缓存任务,本地缓存的API信息并没有配置插件,直到 kong-B 节点执行数据库同步操作之后,API新增插件的功能才会生效。
结论:所有的 CRUD 操作将会触发缓存无效,创建类操作(POST,PUT)将会使本地缓存的数据库遗漏无效,并且更新/删除类操作(PATCH,DELETE)将会使本地缓存命中无效。(重点理解)
你可以配置三个配置项在 kong 配置文件中,最重要的配置项是db_update_frequency,该配置决定你的 kong 节点从性能和强一致性中做出权衡。
kong 已经提供了默认的配置,为了让你权衡集群性能和数据一致性两个方面,避免意外的结果。你可以按照下面的配置步骤,改变配置的值,从而确保性能和数据一致性能够被接受。
该配置决定 kong 节点从数据库拉取缓存无效事件,同步任务执行的频率。一个更小的值意味着同步任务将会更频繁的执行,kong 节点的缓存数据将保持和数据库更强的一致性。一个更大的值,意味着你的 kong 节点花更少的时间去处理同步任务,从而更加将更多资源集中去处理请求。
笔记:变更将会在db_update_frequency 秒后在整个集群节点中生效。
如果你的数据库也是集群的并且最终一致性的(比如:Cassandra),你必须配置该值。它将确保db_update_propagation秒后,数据库节点间的变化在整个数据库集群中所有节点生效。当配置了该值,kong 节点从同步任务中接收无效事件,清除本地缓存将会延迟 db_update_propagation 秒。
如果一个 kong 节点连接到最终一致性数据库上,且没有延迟事件需要处理,它可能会清除缓存,然后把没有更新的值再次缓存起来。(因为这个改变还没有传播到数据库集群的每一个节点,注释:数据库一致性还没有在数据库集群中达到一致,此时kong缓存到期了,但是没有更新到变化事件,此时会把没有更新的值再次缓存起来,导致kong也出现不一致,即便kong执行了同步任务。)。
你应该配置该值,通过评估数据库集群发生变更后,最终达到一致性所需要的时间。(确保数据库一致之后,才去执行 kong 同步任务处理变更事件,从而达到kong 数据一致性)
笔记:当配置了该配置项,数据变更传播到 kong 集群的最大时间是 db_update_frequency + db_update_propagation 秒。
该配置项的时间(单位秒)是 kong 缓存数据库实体的时间(包括缓存命中或者穿透),该存活时间是一种保护措施,以防 kong 节点漏掉处理缓存无效事件,避免旧数据长时间没有被清理。当缓存生存时间到了,缓存值将会被清理掉,下一次将会从数据库读取数据并再次缓存起来。
如果你使用 Cassandra 作为 kong 的数据库,你必须配置 db_update_propagation 为一个非零值。由于 Cassandra 本身是最终一致性数据库,这将确保 kong 节点不会过早地使本地缓存失效,仅仅当再次获取到一个不是最新值的时候。如果你使用了 Cassandra 但你没有配置该值时,kong 将会输出一条警告日志。
此外,你可以配置 cassandra_consistency 的值为:比如 QUORUM 或者 LOCAL_QUORUM,确保被kong 缓存的值是数据库中最新的。
(延伸:此处需要了解 cassandra 数据库最终一致性策略,包括”ALL”, “EACH_QUORUM”, “QUORUM”, “LOCAL_QUORUM”, “ONE”,”TWO”, “THREE”, “LOCAL_ONE” 等策略,有关这些策略集的介绍,请参考:http://dongxicheng.org/nosql/cassandra-strategy/)
由于某些原因,你希望通过 kong 查看缓存的值,或者手动清理缓存(当缓存被命中或者丢失),你可以通过使用 Admin api /cache 接口进行管理。
检查缓存
请求链接
GET /cache/{cache_key}
返回值
当 key 被有效缓存:
HTTP 200 OK
...
{
...
}
否则:
HTTP 404 Not Found
笔记:通过 kong 检查 cache_key 对应的实体是否被缓存,当前没有文档介绍,将来的版本,Admin api 将会提供明确的操作步骤。
清理缓存
请求链接
DELETE /cache/{cache_key}
HTTP 204 No Content
...
清理 kong 节点缓存
DELETE /cache
HTTP 204 No Content
...
笔记:请谨慎在生产运行环境使用这个功能,当 kong 正在处理很多请求时,此时清理 kong 节点的本地缓存将会触发很多 DB 操作,可能会导致缓存穿透,DB请求堆积的现象。