nginx连接资源管理
本文介绍在nginx中连接资源(即ngx_connection_t)的管理与使用。
连接池的初始化
在ngx_cycle_t结构体中维护了几个和连接相关的数据,具体如下
struct ngx_cycle_s {
....
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
ngx_uint_t connection_n;
ngx_connection_t *connections;
ngx_event_t *read_events;
ngx_event_t *write_events;
}
逐一说明一下
- connection_n表示最大的连接数量,通过配置项worker_connections设置
- connections、read_events、write_events都是数组,数组大小为connection_n,且下标都是一一对应,例如connections[i]、read_events[i]、write_events[i]一定是配套使用的一组。connections[i].read = read_events[i],connections[i].write=write_events[i]也始终是成立的。
- free_connections是一个链表的头部,表示空闲的链接,free_connection_n表示空闲连接的数量。
- 空闲的链表通过c[i].data当作next指针逐一串联
- 利用一个free链管理一个资源池的方式与filter中的ngx_output_chain_ctx_t.free类似
- 上述相关资源的初始化都发生在ngx_event_process_init()函数中,即在worker进程初始化时完成。
关于free链结构可以参考ngx_event_process_init()中的代码
c = 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;
连接的申请与释放
连接的申请与释放就是对cycle->free_connections的操作,相关的函数有2个ngx_get_connection()与ngx_free_connection().核心的逻辑可以参考代码
ngx_connection_t *
ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
{
...
c = ngx_cycle->free_connections;
ngx_cycle->free_connections = c->data;
ngx_cycle->free_connection_n--;
...
}
void
ngx_free_connection(ngx_connection_t *c)
{
c->data = ngx_cycle->free_connections;
ngx_cycle->free_connections = c;
ngx_cycle->free_connection_n++;
...
}
连接的典型场景
通过查看ngx_get_connection()与的引用,可以看到连接的主要使用场景
- 场景一:作为监听fd的管理,在ngx_event_process_init()函数中会为cycle->listening中的每个监听绑定一个connection对象,并把connection对象的read事件处理函数设置为ngx_event_accept。
- 场景二:accept连接后的管理,在ngx_event_accept()中,在accept获得新连接后会通过connection进行管理,也是业务开发中reqeust->connection对象的来源。
- 场景三:当nginx需要作为客户端发起请求时,调用ngx_event_connect_peer()函数,也会从连接池中申请资源,这个也是upstream->peer.connection对象的来源。