【Nginx03】Nginx学习:事件模块Event

2023-08-09 11:13:15 浏览数 (1)

Nginx学习:事件模块Event

基础的核心模块中,事件模块是非常重要的一个部分,但是,它的配置项其实并不多,常见的或者说需要我们去配置的更少。不过本着基础学习和了解的态度,咱们还是要一个个的学习一下。

首先来看一下什么是事件模块。在 Nginx 中,模块相关的配置都是在一对大花括号中的,比如 http{} 、server{} 这些,事件模块也是类似的。

代码语言:javascript复制
events {……………………}

事件模块主要是提供配置文件上下文,指定一些影响连接处理的指令,它包含 Nginx 中所有处理连接的设置。为啥事件模块处理的是连接?

其实,这牵涉到 Nginx 的内核运行机制,一般情况下,我们现在使用的 Linux 都支持包括 select、epoll、kqueue 这一类的 IO 模型。而这些模型现在基本都可以看成是事件机制的处理形式,只是内部略有不同。所以在命名上使用了 events ,但实际上管理的是 IO 连接。

具体的这些内容,我也只是了解个大概,比如现在最主流的就是 epoll ,它是完全的事件机制,可以实现多路 IO 复用。当一个 IO 阻塞后,让其它的 IO 继续处理,然后这个 IO 处理完成后触发事件回调回来继续处理。很像我们在日常开发中的回调函数之类的处理流程。Redis 现在主要也是依托于这种 IO 机制实现强大的处理性能。

更详细的内容大家可以再深入的查找相关的学习资料,将来如果咱们要深入学习操作系统时,也可能会接触到,到时候再说吧,现在我的水平也只能解释到这里了。

好了,接下来我们就看看在具体的 events 模块中,我们可以进行哪些配置。

指定 IO 模块

使用的是 use ,注意,和 user 只差一个 r 哦,而且它是写在 events 的花括号里面的。

代码语言:javascript复制
use method;

指定要使用的连接处理方法,可用指定为 select、poll、kqueue、epoll 等等,注意,不同的操作系统使用的也不一样。现在 Linux 下,基本都是 epoll ,FreeBSD 之类的会使用 kqueue ,其它的还有 eventport 等在一些我们不太常见的操作系统上可以配置。这个选项通常不需要显式指定,因为 Nginx 会默认使用当前系统中最有效的模式。

换句话说,如果像我一样,对 IO 模型不太了解的,别设置这玩意了,让他走默认的就好。

代码语言:javascript复制
worker_aio_requests number;

这个命令是将 aio 与 epoll 连接处理方法一起使用时,设置单个工作进程未完成的异步 IO 操作的最大数量。这个配置指令出现在版本1.1.4和1.0.7中。现在有没有用我也不清楚,反正直接配置是不会报错的。使用上也没见到有什么异常。

连接数

上回我们讲过一个 worker_rlimit_nofile ,它是 Nginx 整体的连接数,和系统的 ulimit 有点关系,或者说直接就是可以替换 ulimit 的功能,不过仅限于在 Nginx 环境中哈。今天再来学习的是事件模块中设置工作进程可以打开的最大连接数。

代码语言:javascript复制
worker_connections number;

它设置的是工作进程可以打开的最大同时连接数。这个数字包括所有连接(例如与代理服务器的连接等),而不仅仅是与客户端的连接。另一个考虑因素是,同时连接的实际数量不能超过当前打开文件的最大数量限制,也就是说,它不应该超过 worker_rlimit_nofile 设置的数量。如果 Nginx 配置文件中没有配置的话,要看下操作系统的 ulimit 大小。

另外,我们通过 worker_connections 和上篇文章中学习过的 worker_processes 可以计算出 maxclients (最大连接数):

代码语言:javascript复制
max_clients = worker_processes * worker_connections

如果作为反向代理,max_clients为(除4并不一定准,是个经验值):

代码语言:javascript复制
max_clients = worker_processes * worker_connections/4

worker_processes 是工作进程数,worker_connections 是工作连接数。假如设置当前 CPU 是 4 核,worker_processes 设置为 4 ;worker_connections 也设置到 10000,那么总体的最大连接数就是 4 * 10000= 40000 。

默认情况下,worker_connections 都是 512 或 1024 ,这个数字并不是说越多越好,而是要根据服务器的实际情况进行确定,一个是内存,一个是 ulimit 数量。ulimit 数量一般我们在服务器上会放到最大,因此主要就是内存。通常一个连接对应一读一写两个事件,两个事件大概占用 96 字节,连接内部大概占用 232 字节,总共 328 字节,100000 连接大概占用 31M = 100000 * 328 / 1024 / 1024 。不过具体的还是要根据实际情况来确定,因为上面的计算只是 Nginx 启动时没有其它任务处理的最简单的连接占用的内存。而且处理的连接越多,CPU 负荷也越大。不过大家可以参考一些面板工具设置的默认值是多少,比如宝塔设置的 worker_rlimit_nofile 和 worker_connections 都是 51200 。

以上配置说明为网上找的以及结合一些自己的理解,有实际经验或者研究过这一块的大佬可以留言哈,说实话,我也没怎么配过这个东西,但是,如果 worker_connections 给少了,会明显地出现一个报错,那就是 Too many open files 这个问题。一旦看到这个错误,就应该检查 ulimit、worker_rlimit_nofile、worker_connections 这些配置的情况,看是不是给得太少了。

其它

在事件模块中,还有一些平常见得不多的配置,咱们最后一起来了解下。

互斥锁相关

代码语言:javascript复制
accept_mutex on | off;

accept_mutex 是 Nginx 中不同连接之间是否使用互斥锁进行顺序 accept() 系统调用的配置。如果设置为 on ,则工作进程将依次接受新连接。否则,所有工作进程都会收到有关新连接的通知,如果新连接的数量较低,则一些工作进程可能会浪费系统资源。

在支持 EPOLLEXCLUSIVE 标志(1.11.3)的系统上或使用 reuseport (HTTP模块中的配置)时,无需启用 accept_mutex 。在版本1.11.3之前,默认值为 on ,现在默认是 off 了。

这个配置最主要的作用是可以用来解决常说的“惊群”问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个 worker 进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响 Nginx 的整体性能。如果设置为 on ,将会对多个 Nginx 进程接收连接进行序列化,一个个来唤醒接收,就防止了多个进程对连接的争抢。

代码语言:javascript复制
accept_mutex_delay time;

默认值是 500ms ,和 accept_mutex 相关。如果启用了 accept_mutex ,可以指定某个工作进程检测到其它工作进程正在接入新连接时,自身等待直到重新开始尝试接入新连接的最大时间间隔。

debug_connection

代码语言:javascript复制
debug_connection address | CIDR | unix:;

开启针对特定客户端连接的调试日志。除开这些连接,其它连接将使用 error_log 指令设置的日志级别。 被调试的连接可以使用 IPv4 或 IPv6 (1.3.0, 1.2.1) 网络地址来指定, 也可以使用主机名来设置连接。 对于UNIX域套接字 (1.3.0, 1.2.1),使用 “unix:” 参数来启用调试日志。

干嘛用得?不知道,有用过的同学记得留言,我们一起学习哈。

multi_accept

代码语言:javascript复制
multi_accept on | off;

如果禁用 multi_accept ,工作进程将一次接受一个新连接。否则,工作进程将一次接受所有新连接。如果使用 kqueue 连接处理方式,则忽略该指令,因为 kqueue 可以报告有多少新连接等待接入。

在很多面板应用中,这个配置会打开。

总结

学了一圈,其实我们会发现一个问题,那就是 events 中的内容其实大部分不太需要我们去配置。正常编译安装之后的 events 是这样的。

代码语言:javascript复制
events {
 worker_connections  1024;
}

而 宝塔面板 在一台 CentOS 的服务器默认安装完之后是这样的。

代码语言:javascript复制
events
{
  use epoll;
  worker_connections 51200;
  multi_accept on;
}

就像上面各个配置中说到的,use 其实可以不用配,然后比较重要的就是 worker_connections ,如果是我自己配的话,直接就上 65535 了,另外 multi_accept 可以打开。更具体的配置,大家还是要根据业务情况,或者请教对这一块有更深入研究的运维大佬们,同样的,有心得的小伙伴记得留言,咱们大家一起学习进步哦!

参考文档:

http://nginx.org/en/docs/ngx_core_module.html

http://nginx.org/en/docs/events.html

0 人点赞