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 核心支持的 共享内存 ,如下图
简单来说 :
所有进程都会访问同一块内存获取数据
每个进程会定时轮询检查内存数据是否变化,变化了做相关事件处理
进程都在访问共享内存都有相应的 lock 以保证事件准确
那么 Kong 认为它有什么样的缺陷呢?
由于要访问共享内存需要锁,当 worker 数量非常大时,比如 36+ 以上时,开销就很高了
定时器也会在没有事件时不断运行,这导致了不必要的 cpu 消耗
定时器的频率同样非常低效,每秒一次的检查导致无法快速响应事件
共享内存也存在大小限制,如果事件过多,超过内存大小会导致内存溢出而丢失后续事件
lua-resty-events
在这个云原生和巨大的流量时代,需要改变这种状况。我们需要一种新的事件传播机制,可以更便宜、更高效地将事件发布到每个工作进程。
事实上,Nginx 本身就有一个有效的事件机制,就是 Linux epoll 和 Nginx 异步回调相结合的 event loop。仅通过这种事件机制,Nginx 就可以处理 10k/100k 并发连接,并作为 Kong 网关高性能的核心。
所以 Kong 有一个有趣的想法:为什么我们不能放弃共享内存并将 nginx 自定义到一个特殊的事件通知系统中? 因此编写了一些 POC 代码来验证这个想法,并实现了一个名为 lua-resty-events 的新事件库。
它是如何运作的
基本上,这个库是一个经典的发布/订阅系统,它是一个广泛使用和验证的异步消息/事件调度机制。
我们在此发布/订阅系统中有三个角色:
事件代理:在一个且只有一个 Nginx 工作进程中运行的服务。
事件发布者:任何想要发布事件的 Nginx 工作者。
事件订阅者:每个希望接收事件的 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 阶段启动一个计时器发布了很多事件,每个事件的回调都只是一个空函数
同时设置了两个测试用例:
Post 1000 events per 0.5 second in timer context
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
版权声明: 本文为 InfoQ 作者【八苦-瞿昙】的原创文章。
原文链接:【http://xie.infoq.cn/article/f2812f1fe95fd5f66e61b7f9f】。文章转载请联系作者。
评论