Kong 发布了新的版本0.11.0,从这里开始区分了社区版本和商业版。这次改动比较大的是丢弃了 serf,这样整个 Kong 节点之间的缓存同步方式变化了。开发者给出的理由如下:
- 依赖 serf,serf 并不属于 Nginx/OpenResty
- 这种依赖相互间通信来同步的机制对于 deployment 和容器化都有些不便
- 在运行的 Kong 节点触发 serf 需要一些租塞的 I/O
新的实现的思路是以数据库作为中心,增加一个 cluster events 的表。任何 Kong node 都可以向数据库发送变更消息,其他节点 polling 数据库改动,然后来更新缓存内容。这个改动非常大,不过最终 Kong 终于实现了节点无状态,之前那个数据库里的 nodes 可以丢弃掉了,任何时候节点重启只要连上数据库即可工作。我们需要担心的是这么多节点去 polling 数据库 (当然这些动作都是在后台),是否是一个比较耗时的工作。
Kong 增加了新的配置选项 db_update_frequency,默认为 5s,表示多长时间 polling 一次,这需要用户自己权衡效率和及时性了。对于我们的业务来说及时性还是很重要的,比如我们新品发布时间精确到秒,那么我们就需要尽量调低这个参数。
所有的改动在 https://github.com/Mashape/kong/pull/2561/files,
我大概看了一下代码,一些值得注意的地方如下:
- cluster 相关的 API 和 cmd 都被移掉了,启动部分和 serf 信号处理部分都删掉了不少代码。
- polling 需要避免一个问题,比如上一次 polling 还未执行完成,下一次 polling 就不应该启动,所以这里需要锁来处理。kong/cluster_events.lua实现了 polling 的主要过程。
- kong/cluster_events/strategies/postgres.lua目前 polling 还不支持分页,cluster_events 是一个新建的表用来存储缓存更新事件,Kong 节点就是来查询这些事件。
- 缓存部分换成了lua-resty-mlcache,原来还是和之前分析的类似 L1 级别缓存为一个 LURcache,在 LuaVM 里可见,L2 级别的缓存为 lua_shared_dict,同一个 Nginx 下的所有 worker 可见,L3 就是缓存未命中的情况,需要调用其他 hookup 的函数去获取数据然后缓存在 L2。只是这里个 ipc 并不是用的 lua-resty-mlcache 里的,而是使用的 resty.worker.events。
- 事件处理部分分两部分,worker 之间的事件和 node 之间的处理,分别由 worker_events 和 cluster_event.lua 来处理。