在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对象的来源。