写点什么

Kong 重构了其事件通知机制

作者:八苦-瞿昙
  • 2022 年 9 月 23 日
    中国台湾
  • 本文字数:1788 字

    阅读完需:约 6 分钟

Kong重构了其事件通知机制

openresty 领域一直以来被大家认可(其实也是唯一知名)的事件通知库为 Kong 开发的 lua-resty-worker-events

但是 2022 年初,Kong 开始了废弃 lua-resty-worker-events 而建立的 lua-resty-events 

目前已经完成并在 Kong 3.0 版本已切换

那么为什么 Kong 会放弃使用多年稳定的老库呢?

lua-resty-worker-events 是如何工作?

众所周知 nginx 是多进程模型,如果要进行不同进程之间的相互通讯,就必须采用 ipc 通信

lua-resty-worker-events 采用的就是 ipc 通信效率高, 也是 openresty 核心支持的 共享内存 ,如下图



简单来说 :

  1. 所有进程都会访问同一块内存获取数据

  2. 每个进程会定时轮询检查内存数据是否变化,变化了做相关事件处理

  3. 进程都在访问共享内存都有相应的 lock 以保证事件准确



那么 Kong 认为它有什么样的缺陷呢?

  1. 由于要访问共享内存需要锁,当 worker 数量非常大时,比如 36+ 以上时,开销就很高了

  2. 定时器也会在没有事件时不断运行,这导致了不必要的 cpu 消耗

  3. 定时器的频率同样非常低效,每秒一次的检查导致无法快速响应事件

  4. 共享内存也存在大小限制,如果事件过多,超过内存大小会导致内存溢出而丢失后续事件

lua-resty-events

在这个云原生和巨大的流量时代,需要改变这种状况。我们需要一种新的事件传播机制,可以更便宜、更高效地将事件发布到每个工作进程。

事实上,Nginx 本身就有一个有效的事件机制,就是 Linux epoll 和 Nginx 异步回调相结合的 event loop。仅通过这种事件机制,Nginx 就可以处理 10k/100k 并发连接,并作为 Kong 网关高性能的核心。



所以 Kong 有一个有趣的想法:为什么我们不能放弃共享内存并将 nginx 自定义到一个特殊的事件通知系统中? 因此编写了一些 POC 代码来验证这个想法,并实现了一个名为 lua-resty-events 的新事件库。

它是如何运作的

基本上,这个库是一个经典的发布/订阅系统,它是一个广泛使用和验证的异步消息/事件调度机制。

我们在此发布/订阅系统中有三个角色:

  1. 事件代理:在一个且只有一个 Nginx 工作进程中运行的服务。

  2. 事件发布者:任何想要发布事件的 Nginx 工作者。

  3. 事件订阅者:每个希望接收事件的 Nginx 工作进程。

最后两个角色通常可以是相同的 Nginx 工作者,我们也可以称之为事件用户/事件客户端。相对而言,事件代理可以称为事件服务器。

事件代理侦听 UNIX 域套接字,事件用户使用 Lua cosocket (OpenResty) 连接到事件代理。


因此,如果一个事件用户想要发布事件,唯一需要做的就是通过套接字将序列化的消息发送到事件代理。事件代理将立即接收它,没有任何延迟,然后将其广播给所有事件用户。由于高效的 Nginx,几乎同时,用户将获得并检查事件消息,并做他们想做的事情。

在这个过程中我们不需要使用共享内存和 ngx.timer,所以我们消除了锁定和轮询的成本,非常快速和敏感,所有的工作都依赖于底层框架,这要归功于 Nginx 和 OpenResty。


Kong 的性能比较结果

Benchmarking performance

为了检查 lua-resty-事件库的性能,我们设置了一个基于 OpenResty 1.21.4.1 的测试环境.

使用了三台 AWS c4.8xlarge VMs, 都有 36 cores, 60GB memory, and 1000M network bandwidth. 一个用于 wrk client, 一个用于 OpenResty Server, 一个用于 Nginx backend.


同时修改了 nginx.conf 配置 :

  • worker_processes auto

  • worker_rlimit_nofile 500000

  • worker_connections 400000

  • lua_socket_log_errors off

  • access_log off

  • 在 init_worker 阶段启动一个计时器发布了很多事件,每个事件的回调都只是一个空函数


同时设置了两个测试用例:

  1. Post 1000 events per 0.5 second in timer context

  2. Post 10000 events per 0.1 second in timer context


然后运行 wrk 以下测试命令做压力测试 :

wrk -c 10000 -t 36 -d 3m –latency http://172.31.23.50:8080

结果:




如您所见,在第一种情况下,lua-resty-事件和 lua-resty-worker-事件几乎相同,但在第二种情况下,lua-resty-事件优于 lua-resty-worker-事件,RPS 上升了约 50%。它表明,lua-resty-事件在大型事件中具有更好的表现。

在这两种情况下,lua-resty-事件的延迟都优于 lua-resty-worker-事件。

我们还观察到,在第二种情况下,lua-resty-worker-事件的 CPU 使用率约为 70%-90%,但 lua-resty-事件的 CPU 使用率约为 50%。原因是 lua-resty-worker-事件使用更多的 CPU 来操作共享内存,但 lua-rest-事件对此没有成本。


原文: https://konghq.com/blog/nginx-openresty-event-handling-strategy-for-cpu-efficiency

发布于: 刚刚阅读数: 4
用户头像

八苦-瞿昙

关注

一个假和尚,不懂人情世故。 2018.11.23 加入

会点点技术,能写些代码,只爱静静。 g hub: https://github.com/fs7744 黑历史:https://www.cnblogs.com/fs7744

评论

发布
暂无评论
Kong重构了其事件通知机制_Event_八苦-瞿昙_InfoQ写作社区