perrynzhou

专注于系统组件研发

0%

nginx 如何worker进程的请求处理的负载均衡

nginx 如何worker进程的请求处理的负载均衡

  • nginx 自身实现避免了进群效应,每一个请求上来仅仅只会有一个worker_process处理,nginx 作为静态资源服务器,最大请求连接数为:worker_process * connections;如果作为反向代理,则支撑的最大连接数为worker_process * conenctions/2,因为反向代理需要连接后端的服务,同时也会连接前端请求的。那nginx如何做到请求处理的负载均衡?
  • nginx 核心逻辑调试
1
2
3
4
5
6
7
$ ./configure --with-debug --with-cc-opt='-g -O0' --prefix=/usr/local/nginx
$ make -j4
$ make install

//在配置文件中添加调试配置
daemon off;
master_process off;
  • ngx_worker_process_cycle是每个worker进程核心执行的函数,所有的请求处理都是通过这个函数入口进行
    1
    2
    3
    4
    5
    6
    7
    8
    9

    static void
    ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
    {
    ngx_worker_process_init(cycle, worker);
    for ( ;; ) {
    ngx_process_events_and_timers(cycle);
    }
    }
  • ngx_process_events_and_timers是接受客户请求的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void
ngx_process_events_and_timers(ngx_cycle_t *cycle)
{
if (ngx_use_accept_mutex) {
if (ngx_accept_disabled > 0) {
ngx_accept_disabled--;

} else {
if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
return;
}
}
//这里ngx_process_events宏定义的是ngx_epoll_process_events函数
(void) ngx_process_events(cycle, timer, flags);
}
  • ngx_epoll_process_events 通过多层次的请求最终函数调用会落在ngx_event_accept,最终处理来自客户端的请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
events = epoll_wait(ep, event_list, (int) nevents, timer);
for (i = 0; i < events; i++) {
c = event_list[i].data.ptr;

instance = (uintptr_t) c & 1;
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

rev = c->read;
//(gdb) p rev->handler
//$3 = (ngx_event_handler_pt) 0x5555555cb7f6 <ngx_http_wait_request_handler>
rev->handler(rev);
}

}

void ngx_event_accept(ngx_event_t *ev)
{
ngx_accept_disabled = ngx_cycle->connection_n / 8- ngx_cycle->free_connection_n;
ngx_listening_t *ls;
/*
(gdb) p ls->handler
$5 = (ngx_connection_handler_pt) 0x5555555cb32d
<ngx_http_init_connection>
*/
ls->handler(c);

}
  • nginx 通过ngx_accept_disabled来协调当前worker是否应该接受处理来自客户端请求吗,在ngx_event_accept中,设置ngx_accept_disabled为当前worker进程的连接数的1/8 减去当前空间连接,这个ngx_accept_disabled越大,空闲连接就越小,说明当前worker进程比较繁忙,让出请求处理的特权,其他的worker可以去处理。