IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Nginx的connections数组

淘宝数据平台与产品部官方博客 tbdata.org 2010-12-14 21:58:24 累计浏览 3,723 次
本机暂存

本文的标题让我纠结了好久,不知道是connections数组合适,还是connections链表更合适;Nginx在此或多或少的注入了二者的特点,先不管是叫数组还是叫链表吧,只要能够弄明白这个connections是怎么回事就大功告成。Nginx的每个worker进程都使用一个相同的connections数组来维护每个连接。当有一个新的连接建立时,Nginx需要从这个数组取出一个slot来存放这个连接;相反,有一个连接断开时,也需要将相应的slot归还给connections数组。本文就来看一下这个connections数组是如何构造的,能够让Nginx方便,快速的获取/释放一个slot。我从ngx_event_process_init()函数中拼凑了如下一段代码:

/*分配数组*/
cycle->connections =
        ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
if (cycle->connections == NULL) {
        return NGX_ERROR;
}
c = cycle->connections;
i = cycle->connection_n;
next = NULL;

/*将数组中的所有slot用指针串起来,形成一个链表*/
do {
        i--;
        c[i].data = next;
        。。。。。。。。。。。。。。。。。
        next = &c[i];
} while (i);
/*free_connections指向一个可用的slot*/
cycle->free_connections = next;
/*free_connection_n可用slot的个数*/
cycle->free_connection_n = cycle->connection_n;

经过上述代码过后,形成的数据结构如下图所示:
原图已失效

现在,Nginx已经为我们构造起了一个空的connections数组,我们需要建立一个新的连接,因此调用函数ngx_get_connection()从connections数组中获取一个可用的slot来维护这个连接。首先,我们看一下ngx_get_connection()函数的简化实现:

ngx_connection_t *
ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
{
    ngx_uint_t         instance;
    ngx_event_t       *rev, *wev;
    ngx_connection_t  *c;
	。。。。。。。。。。。。

	/*从free_connecionts处就能够直接获得一个可用的slot*/
    c = ngx_cycle->free_connections;
    if (c == NULL) {
        return NULL;
    }
	/*移动free_connections指针到获取的C的下一个可用slot上*/
    ngx_cycle->free_connections = c->data;
    ngx_cycle->free_connection_n--;
    。。。。。。。。/*省略很多对c的操作*/
    return c;
}

从刚建立的connections数组中获取一个slot后的,效果图如下:
原图已失效

在上述状态下,我们再获取一个slot,那么就得到如下的结果了:
原图已失效

到此,我们基本明白从connections数组中获取一个slot的操作过程了,接下来看看释放一个slot的过程是如何的。和ngx_get_connection()函数对应的是ngx_free_connection()函数。简化实现如下:

void
ngx_free_connection(ngx_connection_t *c)
{
	/*规划的slot c指针可用的slot链表头*/
    c->data = ngx_cycle->free_connections;
    /*移动free_connections到c上*/
    ngx_cycle->free_connections = c;
    ngx_cycle->free_connection_n++;
    。。。。。。。。
}

释放第一次获取的slot后的效果如下:
原图已失效

再释放第二次获取的slot后,又变成如下的效果了:
原图已失效

虽然最后整个connections数组都没有被使用,但和起初创建好的时候,还是有一定的区别的。但最重要的是――所有可以使用的slot都还是照样在一个链表上,只是slot的串联顺序不一样了。本文只是给出了一种很简单很简单的获取释放slot的case。你完全可以异想天开的获取释放slot的顺序,构造出看上去比较复杂的一个链表,但本质始终还是一样的。

一个好的数据结构,不光要高效,还得易用,Nginx在这个connection维护方面,做到了。

同分类推荐文章

  1. Vibe新开源项目 - Vaala AI Gateway (2026-05-17 02:10:19)
  2. SmartPerfetto 架构文章 Q&A:8 个深度技术问答 (2026-04-10 11:00:00)
  3. 让 AI 把我的 PHP 博客重写成 Go (2026-03-27 18:33:54)

查看更多 后端 文章 →

建议继续学习

  1. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 106,963)
  2. 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (累计阅读 33,822)
  3. 记录一个软中断问题 (累计阅读 16,885)
  4. 解析nginx负载均衡 (累计阅读 16,503)
  5. server日志的路径分析 (累计阅读 11,181)
  6. Nginx模块开发入门 (累计阅读 11,101)
  7. 检查nginx配置,重载配置以及重启的方法 (累计阅读 10,782)
  8. Cacti 添加 Nginx 监控 (累计阅读 10,521)
  9. 使用Squid缓存视频 (累计阅读 10,280)
  10. fsockopen 异步处理 (累计阅读 10,280)