IT

nginx学习笔记——基础概念

Posted by Loksin on 2017-05-17

connection

  • 在nginx中connection就是对tcp连接的封装,其中包括连接的socket,读事件、写事件。

  • nginx中的http请求的处理就是建立在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    * nginx可以作为客户端来请求其它server的数据的(如```upstream```模块),与其它server创建的连接,也封装在```ngx_connection_t```中。
    流程为:
    > ①先获取一个```ngx_connection_t```结构体。②创建socket并设置其属性( 比如非阻塞)。③通过添加读写事件,调用```connect/read/write```来调用连接。④关闭连接,并释放```ngx_connection_t```。

    * 每个进程会有一个连接数的最大上限,通过```ulimit -n```可以得到一个进程所能够打开的fd的最大数即nofile。nginx通过设置```worker_connectons```来设置*每个进程支持的最大连接数*,如果该值大于nofile,那么实际的最大连接数是nofile。

    * nginx在实现时,是通过一个连接池来管理的,每个worker进程都有一个独立的连接池,连接池的大小是```worker_connections```。这里的连接池里面保存的不是真实的连接,它只是一个```worker_connections```大小的一个```ngx_connection_t```结构的数组。

    * nginx会通过一个链表```free_connections```来保存所有的空闲```ngx_connection_t```,每次获取一个连接时,就从空闲连接链表中获取一个,用完后,再放回空闲连接链表里面。

    * 因为```worker_connections```是每个进程的最大连接数,所以整个nginx的总最大连接数为进*进程最大连接数x进程数*即,```worker_connections * worker_processes```。

    * 作为反向代理来说,最大并发数量应该是```worker_connections * worker_processes/2```。因为作为反向代理服务器,每个并发会建立与```客户端```的连接和与```后端服务```的连接,会占用两个连接。

    * 在一个连接到来时nginx的worker进程会抢夺```accept_mutex```,获得```accept_mutex```的进程才添加accept事件,可以通过```ngx_accept_disabled```的变量来控制是否去竞争```accept_mutex```锁。

    ngx_accept_disabled控制进程是否抢占连接过程:

/**

  • 在第一段代码中,计算ngx_accept_disabled的值,这个值是nginx单进程的所有连接总
    数的八分之一,减去剩下的空闲连接数量,得到的这个ngx_accept_disabled有一个规律
    ,当剩余连接数小于总连接数的八分之一时,其值才大于0,而且剩余的连接数越小,这
    个值越大。再看第二段代码,当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) { //不获取accept_mutex锁
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;
    }
}

}



### request