nginx的连接池
1. 连接池的初始化
首先,初始化连接池,
cycle->connections =
ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
if (cycle->connections == NULL) {
return NGX_ERROR;
}
我们可以看到cycle->connections被分配了一个足够的空间。
i = cycle->connection_n;
next = NULL;
do {
i--;
c[i].data = next;
c[i].read = &cycle->read_events[i];
c[i].write = &cycle->write_events[i];
c[i].fd = (ngx_socket_t) -1;
next = &c[i];
} while (i);
cycle->free_connections = next;
cycle->free_connection_n = cycle->connection_n;
初始化完成后,连接池的样子就想一个前一个元素的一个数组。最后,free_connection指向第一个元素。我们可以看下
我们可以看下,初始化后连接池情况:
现在的结果就是,沿着free—>connection—>connection就连成了一串,然后get的时候直接把free_connection拿出来就可以了,然后free_connection指向原来的那个next。
2. 连接的获取
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;
/* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"the new socket has number %d, "
"but only %ui files are available",
s, ngx_cycle->files_n);
return NULL;
}
/* ngx_mutex_lock */
//把free_connections给c,最后会返回c
c = ngx_cycle->free_connections;
//连接池不够了
if (c == NULL) {
ngx_drain_connections();
c = ngx_cycle->free_connections;
}
if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"%ui worker_connections are not enough",
ngx_cycle->connection_n);
/* ngx_mutex_unlock */
return NULL;
}
// free_connections指向下一个可用连接
ngx_cycle->free_connections = c->data;
ngx_cycle->free_connection_n--;
/* ngx_mutex_unlock */
if (ngx_cycle->files) {
ngx_cycle->files[s] = c;
}
rev = c->read;
wev = c->write;
ngx_memzero(c, sizeof(ngx_connection_t));
c->read = rev;
c->write = wev;
c->fd = s;
c->log = log;
instance = rev->instance;
ngx_memzero(rev, sizeof(ngx_event_t));
ngx_memzero(wev, sizeof(ngx_event_t));
rev->instance = !instance;
wev->instance = !instance;
rev->index = NGX_INVALID_INDEX;
wev->index = NGX_INVALID_INDEX;
rev->data = c;
wev->data = c;
wev->write = 1;
return c;
}
我们可以看下,get了三次后的连接池情况:
3. 连接的释放
下面是free_connection的过程,连接释放后,重新加入到连接池的过程很像链表在头指针后插入节点的操作(其实就是),free之后,可能连接池的整体情况不像开始那样“整齐”,不过,我们把他当做链表来看,free_connection是头指针,通过c->data把指针一个一个串了起来,保证下次get的时候,get头节点的,free的时候,也是free头节点。
void
ngx_free_connection(ngx_connection_t *c)
{
/* ngx_mutex_lock */
//free节点next指向
c->data = ngx_cycle->free_connections;
ngx_cycle->free_connections = c;
ngx_cycle->free_connection_n++;
/* ngx_mutex_unlock */
if (ngx_cycle->files) {
ngx_cycle->files[c->fd] = NULL;
}
}
我们可以看下,free了三次后的连接池情况:
以上就是连接池的基本操作。