Nginx之连接

本文介绍了Nginx中连接的概念,包括连接的生命周期、连接数管理和连接控制策略。Nginx通过worker_connections设置每个进程的最大连接数,并使用连接池进行管理。当启用accept_mutex时,Nginx会控制多进程间的连接平衡,防止某些进程过度消耗连接资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

connection

简介

     在Nginx中connection就是封装了TCP连接,其中包括连接的socket,读写事件。利用nginx封装的connection,方便的处理与连接相关的事情,比如,建立连接,发送与接收数据等。Nginx中http请求的处理就是建立在connection上,所以Nginx不仅可以作为一个web服务器,也可以是邮件服务器。我们可以用connection与任何后端服务打交道。

连接

     结合一个TCP连接的生命周期,我们看看nginx对连接的处理。

  1. nginx启动时,会解析配置文件,得到需要监听的端口与IP地址,在nginx的master进程里初始化好这个监控的socket(创建socket,设置addrreuse等选项,绑定到指定的IP地址端口,在listen)
  2. fork出多个子进程,子进程会竞争accept新的链接。
  3. 客户端可以向nginx发起连接了,当客户端与服务端通过三次握手建立一个链接后,nginx的某子进程会accept成功,得到这个建立好的socket,然后创建对nginx的封装,即ngx_connection_t结构体。
  4. 设置读写事件的处理函数并添加读写事件与客户端进行数据交换
  5. 任意一方关闭连接

     nginx也可以作为客户端来请求其他server的数据(如upstream模块),此时,与其他server创建的连接封装在ngx_connection_t中。

  1. 作为客户端,nginx先获取一个ngx_connection_t结构体,然后创建socket,并设置socket的属性(比如非阻塞),
  2. 然后通过添加读写事件,调用connect/read/write来调用连接
  3. 最后关闭连接,释放ngx_connection_t结构体。

连接数

     在nginx中,每个进程有一个连接数的最大上限,这个跟系统对fd的限制不一样。在操作系统中,通过ulimit -n,我们可以得到一个进程所能够打开的fd的最大数,即nofile,因为每个socket连接会占用一个fd,所以这限制了我们进程的最大连接数,直接影响到我们程序所能支持的最大并发数,当fd用完后,在创建socket就会失败。不过这里nginx对连接数的限制与nofile没有直接联系。nginx通过设置worker_connections设置每个进程可使用的连接最大值。nginx实现时,通过一个连接池来管理的,每个worker进程都有一个独立的连接池,连接池的大小是worker_connections。这里连接池不是真实的连接。是一个 worker_connections 大小的一个 ngx_connection_t 结构的数组。并且, nginx 会通过一个链表 free_connections 来保存所有的空闲 ngx_connection_t,每次获取一个连接时,就从空闲连接链表中获取一个,用完后,再放回空闲连接链表里面。

woeker_connections这个值是表示每个 worker 进程所能建立连接的最大值,所以,一个 nginx 能建立的最大连接数,应该是worker_connections * worker_processes。这里说的是最大连接数,对于 HTTP 请求本地资源来说,能够支持的最大并发数量是 worker_connections * worker_processes,而如果是 HTTP 作为反向代理来说,最大并发数量应该是 worker_connections *worker_processes/2。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接。

连接控制

之前说过,一个客户端连接过来后,多个空闲的进程,会竞争这个连接,这种竞争会导致不公平,如果某个进程得到accept机会较多,空闲连接很快就用完了,如果不提前做一些控制,当acceot到一个新tcp连接后,因为无法得到新空闲连接,而且无法将此链接转交给其他进程,最终导致tcp得不到处理,就中止掉了。

那么如何解决呢?

  1. nginx处理得先打开accept_mutex选项,此时,只有获得了 accept_mutex 的进程才会去添加 accept 事件,也就是说, nginx 会控制进程是否添加 accept 事件。nginx 使用一个叫 ngx_accept_disabled 的变量来控制是否去竞争 accept_mutex 锁。
  2. 在第一段代码中,计算 ngx_accept_disabled 的值,这个值是 nginx 单进程的所有连接总数的八分之一,减去剩下的空闲连接数量,得到的这个 ngx_accept_disabled 有一个规律,当剩余连接数小于总连接数的八分之一时,其值才大于 0,而且剩余的连接数越小,这个值越大。
  3. 再看第二段代码,当 ngx_accept_disabled 大于0 时,不会去尝试获取 accept_mutex 锁,并且将 ngx_accept_disabled 减 1,于是,每次执行到此处时,都会去减 1,直到小于 0。不去获取 accept_mutex 锁,就是等于让出获取连接的机会,很显然可以看出,当空余连接越少时, ngx_accept_disable 越大,于是让出的机会就越多,这样其它进程获取锁的机会也就越大。不去 accept,自己的连接就控制下来了,其它进程的连接池就会得到利用,这样,nginx 就控制了多进程间连接的平衡了。

 

ngx_accept_disabled = ngx_cycle->connection_n / 8
    - ngx_cycle->free_connection_n;

if (ngx_accept_disabled > 0) 
{
    ngx_accept_disabled--;
} else {
    if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR)
    {
        return;
    }
    if (ngx_accept_mutex_held) {
        flags |= NGX_POST_EVENTS;
    } else 
    {
        if (timer == NGX_TIMER_INFINITE
            || timer > ngx_accept_mutex_delay)
        {
            timer = ngx_accept_mutex_delay;
        }
    }
}

好了,连接的基本概念就先介绍到这。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值