内存池
struct mp_large_s {
struct mp_large_s *next;
void *alloc;
};
struct mp_node_s {
unsigned char *last;
unsigned char *end;
struct mp_node_s *next;
size_t failed;
};
struct mp_pool_s {
size_t max;
struct mp_node_s *current;
struct mp_large_s *large;
struct mp_node_s head[0]; //零长数组
};
内存池维护节点(node)和大块内存链表,每个节点维护一块固定大小为block_size的内存,节点的end-last为当前节点剩余可分配的内存。初始化的时候,先用posix_memalign分配一块sizeof(struct mp_pool_s) + sizeof(struct mp_node_s)+block_size 的内存, 并转为pool指针。因为pool里的head是一个节点类型的零长数组,它会自动把sizeof(struct mp_pool_s)到sizeof(struct mp_pool_s)+sizeof(struct mp_node_s)这一段的内存当做一个节点。
当我们想从pool中取出一段小于block_size的内存时,需要通过节点的next指针,从当前current节点开始,遍历并找到第一个剩余内存够的节点。若找不到则在尾端插入一个新节点。为了减少遍历的节点数,如果current节点在以前的查找中已经访问了4次,则跳过他使它的next节点为current节点,下次遍历从这个节点开始。
http 入口
ngx_string(“http”)
ngx_http_block
ngx_http_optimize_servers
ngx_http_init_listening
ngx_http_add_listening
ngx_http_init_connection(handler)
ngx_http_wait_request_handle(handler)
ngx_http_process_request_line
ngx_http_process_request_headers
ngx_http_process_request
ngx_http_handler
ngx_http_core_run_phases
phase
11个阶段处理HTTP请求
/**
* 11个阶段处理HTTP请求
*/
void
ngx_http_core_run_phases(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_http_phase_handler_t *ph;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
ph = cmcf->phase_engine.handlers;
/* 遍历解析和处理各个阶段的HTTP请求 如果返回rc==NGX_AGAIN 则交由下一个阶段处理;返回OK则返回结果 */
while (ph[r->phase_handler].checker) {
rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
if (rc == NGX_OK) {
return;
}
}
}
/**
* 内容接收阶段
*/
ngx_int_t
ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
ngx_int_t rc;
/*
* generic phase checker,
* used by the post read and pre-access phases
*/
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"generic phase: %ui", r->phase_handler);
/* handler 回调函数*/
rc = ph->handler(r);
/* 本阶段处理完成,跳转到下一个阶段处理 */
if (rc == NGX_OK) {
r->phase_handler = ph->next;
return NGX_AGAIN;
}
/* 本阶段当前的回调函数处理完成,继续执行本阶段其他回调函数 */
if (rc == NGX_DECLINED) {
r->phase_handler++;
return NGX_AGAIN;
}
if (rc == NGX_AGAIN || rc == NGX_DONE) {
return NGX_OK;
}
/* rc == NGX_ERROR || rc == NGX_HTTP_... */
ngx_http_finalize_request(r, rc);
return NGX_OK;
}
挂载自定义模块
/**
* 模块初始化
*/
static ngx_int_t
ngx_http_static_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
/* 注册到NGX_HTTP_CONTENT_PHASE阶段 */
h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
/* 设置阶段回调函数 */
*h = ngx_http_static_handler;
return NGX_OK;
}
惊群
Nginx中使用mutex互斥锁解决这个问题,具体措施有使用全局互斥锁,每个子进程在epoll_wait()之前先去申请锁,申请到则继续处理,获取不到则等待,并设置了一个负载均衡的算法(当某一个子进程的任务量达到总设置量的7/8时,则不会再尝试去申请锁)来均衡各个进程的任务量。