Nginx在云上环境的性能最佳实践

Nginx在云上环境的性能最佳实践 目录 背景 Nginx的CPU相关设置 k8s的CPU策略 方案对比 结论 背景 最近有用户反馈 ApacheAPISIX 在云原生环境下存在几个问题: 无法获取容器准确核数 配置了多核的情况下吞吐量增长缓慢 这里先简单介绍项目相关的情况,APISIX 是一个基于 Openresty 的开源网关。而 Openresty 其实就是 Nginx + LuaJIT,那么我们要调查问题其实跟 Nginx 是脱不开关系的。 Nginx的CPU相关设置 首先看看第一个问题:无法获取容器准确核数,这个问题的起因是因为在 Nginx 配置中使用了 worker_processes auto; auto 意味 Nginx 会自动获取 CPU 核数,然后根据核数创建 worker。不幸的是,在容器当中它获取到的是 母机的核数 导致 Nginx 会在容器中创建数十个甚至上百个 worker,多个 worker 间的资源竞争和上下文切换都会降低它的性能。 为了核验 Nginx 是否真的获取的是母机核数,我翻了下 Nginx 相关的代码,截取核心片段如下: src/os/unix/ngx_posix_init.c #include <ngx_config.h>#include <ngx_core.h>#include <nginx.h> ngx_int_t ngx_ncpu; ngx_int_t ngx_max_sockets; ngx_uint_t ngx_inherited_nonblocking; ... #if (NGX_HAVE_SC_NPROCESSORS_ONLN) if (ngx_ncpu == 0) { ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); 查看 sysconf 的文档发现底层调用的 get_nprocs_conf(3), 继续查看它的源码,核心片段如下:
查看更多 →

Openresty 笔记

Openresty 笔记 简介 Openresty 是一个国人将LuaJIT嵌入Nginx进程进而可以使用Nginx来进行开发高性能的Web框架。 入门的简介可以参考这个文档,OpenResty 不完全指南 注意点 Openresty 由于是在每个 nginx worker 都运行了一个 luajit 所以它仍然是一个单线程模型所以不存在 并行(parall) 问题,但是用于处理请求的是 lua 的 协程coroutine,那么这里可能存在 并发(parallelism) 问题,即如果 协程A 因为某种原因挂起后yield(IO操作/sleep),此时 协程B 将会被运行,同时共享 模块变量 以及 全局变量。openresty 这种非抢占式的协程调度带来了优点,也有缺点,优点就是不存在多个协程同时进行导致的并发读写问题,缺点在于如果某个协程进行一些长时间的调用,比如计算或者系统调用等,那么整个进程都会被卡主,导致吞吐量大大下降。(go 在 1.14 之后实现了基于信号的抢占式协程调度,由 sysmon 线程来执行检测,每 20us 检测周期,如果发现P的running状态超过 10ms or syscall 超过 20us,那么直接发送信号给 M,让其放弃正在执行的 G,开始执行其他的 G) 使用 Openresty 可以调用 c 的代码,底层是利用了 linux 的 dlsym 和 dlopen 利用后者加载链接库,前者加载函数符号。由于 LuaJIT 与 C 进行交互,所以不会识别 c++ 的机制,比如析构函数,这样一来你就没法使用 c++ 推荐的 RAII 机制。你有两个方式来管理内存:1、c way,在使用完后释放他,这是你的责任 2、lua way 可以在 lua侧包装一下返回的类,再使用 ffi.
查看更多 →