nginx 连接池

2015-06-25 16:13:01   最后更新: 2015-07-26 15:44:30   访问数量:1483




事件模块初始化 过程中创建了连接池以及 read_events 和 write_events 数组,那么 nginx 连接池究竟是一个什么样的结构呢?

 

 

如图所示,nginx 连接池实际上就是一个 ngx_connection_t 类型的数组,由全局变量 cycle 中的 connections 指针指向其起始地址,free_connections 指针指向未使用部分的起始地址,free_connections_n 保存未使用元素个数

数组的每个元素就是一个连接,每个连接又对应一个读事件和一个写事件,他们分别保存在 read_events 和 write_events 数组中,这两个数组的元素都是 ngx_event_t 类型的,并且与 connections 数组长度完全一致,完全同步的设计

 

// struct ngx_connection_s // nginx 连接结构 {{{ struct ngx_connection_s { // 连接未使用时,充当连接池空闲链表中的 next 指针 // 连接使用后,由模块定义其意义 // HTTP 模块中,data 指向 ngx_http_request_t void *data; // 连接对应的读事件 ngx_event_t *read; // 连接对应的写事件 ngx_event_t *write; // 连接 fd ngx_socket_t fd; // 直接接收网络字符流的方法 ngx_recv_pt recv; // 直接发送网络字符流的方法 ngx_send_pt send; // 以链表来接收网络字符流的方法 ngx_recv_chain_pt recv_chain; // 以链表来发送网络字符流的方法 ngx_send_chain_pt send_chain; // 监听对象,此连接由listening监听端口的事件建立 ngx_listening_t *listening; // 这个连接上已发送的字节数 off_t sent; ngx_log_t *log; // 一般在accept一个新的连接时,会创建一个内存池 // 而在这个连接结束时会销毁内存池 // 内存池大小是由 listening 成员的 pool_size 决定的 ngx_pool_t *pool; // 连接客户端的sockaddr struct sockaddr *sockaddr; // sockaddr结构体的长度 socklen_t socklen; // 连接客户段字符串形式的IP地址 ngx_str_t addr_text; // 代理协议地址 ngx_str_t proxy_protocol_addr; #if (NGX_SSL) ngx_ssl_connection_t *ssl; #endif // 本机监听端口对应的sockaddr结构体 struct sockaddr *local_sockaddr; // sockaddr结构体的长度 socklen_t local_socklen; // 用户接受、缓存客户端发来的字符流,分配在连接池中 ngx_buf_t *buffer; // 用来将当前连接以双向链表元素的形式添加到 ngx_cycle_t 核心结构体的 // reuseable_connection_queue 双向链表中,表示可以重用的连接 ngx_queue_t queue; // 连接使用次数 ngx_atomic_uint_t number; // 处理的请求次数 ngx_uint_t requests; // 缓存中业务类型 unsigned buffered:8; // 日志级别 unsigned log_error:3; /* ngx_connection_log_error_e */ // 为1时表示独立的连接,为0表示依靠其他连接行为而建立起来的非独立连接 unsigned unexpected_eof:1; // 为1表示连接已经超时 unsigned timedout:1; // 为1表示连接处理过程中出现错误 unsigned error:1; // 为1表示连接已经销毁 unsigned destroyed:1; // 为1表示连接处于空闲状态,如 keepalive 两次请求中间的状态 unsigned idle:1; // 为1表示连接可重用,与 queue 字段对应使用 unsigned reusable:1; // 为1表示连接关闭 unsigned close:1; // 为1表示正在将文件中的数据发往连接的另一端 unsigned sendfile:1; // 为1表示只有连接套接字对应的发送缓冲区必须满足最低设置的大小阀值时, // 事件驱动模块才会分发该事件 // 这与ngx_handle_write_event方法中的lowat参数是对应的 unsigned sndlowat:1; unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */ unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */ unsigned need_last_buf:1; #if (NGX_HAVE_IOCP) unsigned accept_context_updated:1; #endif #if (NGX_HAVE_AIO_SENDFILE) unsigned aio_sendfile:1; unsigned busy_count:2; ngx_buf_t *busy_sendfile; #endif #if (NGX_THREADS) ngx_atomic_t lock; #endif }; // }}}

 

ngx_connection_s 结构中定义了连接的读写事件指针以及各种标识,每个结构负责描述一个连接

 

// struct ngx_event_s // 事件描述结构体 {{{ struct ngx_event_s { // 事件上下文数据,指向 ngx_connection_t 结构对象 // 对于文件异步 IO,可能指向 ngx_event_aio_t 结构对象 void *data; // 为 1 表示事件可写 unsigned write:1; // 为 1 表示可以建立新的连接 unsigned accept:1; /* used to detect the stale events in kqueue, rtsig, and epoll */ // 判断当前事件是否过期 unsigned instance:1; /* * the event was passed or would be passed to a kernel; * in aio mode - operation was posted. */ // 为 1 表示当前活跃事件 unsigned active:1; // 用于 kqueue 和 rtsing 事件,是否禁用 unsigned disabled:1; /* the ready event; in aio mode 0 means that no operation can be posted */ // 用于异步IO,当有请求需要处理时置位 unsigned ready:1; // 用于 kqueue 和 eventport unsigned oneshot:1; /* aio operation is complete */ // 用于异步 IO 事件,是否已经完成 unsigned complete:1; // 为 1 表示字符流已结束 unsigned eof:1; unsigned error:1; // 为 1 表示事件已超时 unsigned timedout:1; // 为 1 表示该事件存储在定时器中 unsigned timer_set:1; // 仅用于限速功能中,为 1 表示需要延时处理 unsigned delayed:1; // 为 1 表示 TCP 三次握手后暂时不建立连接,等到真正收到数据包后才建立连接 unsigned deferred_accept:1; /* the pending eof reported by kqueue, epoll or in aio chain operation */ // 只用于 kqueue 和 aio 事件中,为 1 表示字符流结束 unsigned pending_eof:1; unsigned posted:1; #if (NGX_WIN32) /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */ unsigned accept_context_updated:1; #endif #if (NGX_HAVE_KQUEUE) unsigned kq_vnode:1; /* the pending errno reported by kqueue */ int kq_errno; #endif /* * kqueue only: * accept: number of sockets that wait to be accepted * read: bytes to read when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * write: available space in buffer when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * * iocp: TODO * * otherwise: * accept: 1 if accept many, 0 otherwise */ #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP) int available; #else unsigned available:1; #endif // 事件发生时处理的回调函数 ngx_event_handler_pt handler; #if (NGX_HAVE_AIO) #if (NGX_HAVE_IOCP) ngx_event_ovlp_t ovlp; #else struct aiocb aiocb; #endif #endif ngx_uint_t index; ngx_log_t *log; // 定时器节点 ngx_rbtree_node_t timer; /* the posted queue */ ngx_queue_t queue; // 为 1 表示当前事件已关闭 unsigned closed:1; /* to test on worker exit */ unsigned channel:1; unsigned resolver:1; #if 0 /* the threads support */ /* * the event thread context, we store it here * if $(CC) does not understand __thread declaration * and pthread_getspecific() is too costly */ void *thr_ctx; #if (NGX_EVENT_T_PADDING) /* event should not cross cache line in SMP */ uint32_t padding[NGX_EVENT_T_PADDING]; #endif #endif }; // }}}

 

 

ngx_event_t 结构中定义了时间所需的各种标志位以及回调函数指针

 

由于 ngx_connection_t 结构中定义了接的读写事件指针,当调用:

ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log);

 

即可获取连接池中该套接字上的连接,同时也就随之返回了读写事件指针

 






技术帖      socket      龙潭书斋      nginx      连接池      连接      connection      event      ngx_connection_t      ngx_event_t      ngx_socket_t     


京ICP备15018585号