Author: haoransun
Wechat: SHR—97
学习来源:极客时间-Nginx核心知识100讲,本人购买课程后依据视频讲解汇总成个人见解。
前言
之前谈到的Nginx中的读写事件,这些网络读写事件究竟是怎样的应用到Nginx上的呢?
Nginx使用了连接池来增加它对资源的利用率。
Nginx通过连接池处理网络请求
连接池
右边图中每一个Worker进程中都有一个独立的数据结构:ngx_cycle_t。其中有三个中重要的数据。
- connection数组:即连接池,他指向的数组有多大呢?其实是有一个配置项可以查看的。512大小的数组。
- read_event数组:数组大小与上述配置一致。
- write_event数组:同上。
三者通过序号对应,5号连接自然对应5号读写事件。
核心数据结构
一般是 235 + 96*2 (乘2是因为读写两个分配)。
rb_tree_node_t 红黑树中每个节点指向的 timer,标志读写事件是否超时。
定时器也是可配置的。
ngx_queue_t 事件进队列。
右边的 off_t 可以理解为一个无符号的变量,即已经向客户端发送了多少字节。
这个也是可配置的。
在access.log中可以看到上述配置生效。
小结
以上是 ngx_connection_t 与 ngx_event的配置。即连接与事件是怎样对应在一起的。当我们需要配置高并发的nginx时,需要将connection的数目配置的足够大。每一个connection对应的两个event(读写)都会消耗一定的内存。Nginx结构体中的许多成员与内置变量是可以对应做配置的。
Nginx内存池对性能的影响
如果开发过第三方模块,会发现虽然在写C语言代码,但我们不需要关心内存的释放。如果在配置一些比较罕见的Nginx使用场景,可能需要去修改Nginx在请求和连接上初始分配的内存池大小。Nginx官方通常推荐不需要修改有关配置。究竟要不要改呢?
内存池运转方式
在上面的 核心数据结构中,发现ngx_connection_s结构体中有一个ngx_pool_t 结构。它对应着当前连接所使用的内存池,可以通过 connection_pool_size去定义。
内存池
连接内存池上只分配一次,只要连接不关闭,分配的内存永远不需要释放,只有当关闭连接时才会释放。
请求内存池:每一个HTTP请求开始分配时并不知道分配多少合适,但对于HTTP1.1 通常分配 4k大小(URL、Header往往需要这么多)。如果没有内存池,可能需要频繁而小块的分配,可能会造成内存碎片过多这样的代价。
当分配的内存超过 256|521 这种预分配大小时,还是可以继续分配的,这里只是提前分配空间,为了减少分配次数。
请求内存池大小
对于连接而言,他所需要的空间很小,只需要帮助后面的请求读取最初的一部分字节就ok了,而对于请求而言,要保存大量的上下文信息(URL、Header)等。如果URL过大,可以考虑修改这个配置项。