nginx网络层分析

时间:2022-02-17 02:25:22

近来有空阅读了一下高性能开源http服务器nginx的源代码,因为整个代码有接近10w行,所以只能先分析一下我比较关心的网络层的连接处理。


首先从主函数main进去,前面的配置初始化先略过,看到如下代码:

    if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle);

} else {
ngx_master_process_cycle(cycle);
}
一般来说使用多进程进行处理,也就是执行ngx_master_process_cycle(cycle);然后进去函数里面看到这句代码:

    ngx_start_worker_processes(cycle, ccf->worker_processes,
NGX_PROCESS_RESPAWN);

就是启动worker子进程,nginx是使用多个worker进程来处理连接,然后有master主进程进行管理的。进入函数里:

    for (i = 0; i < n; i++) {

cpu_affinity = ngx_get_cpu_affinity(i);

ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
"worker process", type);

ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];

ngx_pass_open_channel(cycle, &ch);
}
看到ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,  "worker process", type);函数,创建若干个worker进程,ngx_worker_process_cycle通过函数指针传入是worker实际工作的函数。

接着进入ngx_worker_process_cycle函数里:

#if (NGX_THREADS)
{
ngx_int_t n;
ngx_err_t err;
ngx_core_conf_t *ccf;

ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

if (ngx_threads_n) {
if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
== NGX_ERROR)
{
/* fatal */
exit(2);
}

err = ngx_thread_key_create(&ngx_core_tls_key);
if (err != 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
ngx_thread_key_create_n " failed");
/* fatal */
exit(2);
}

for (n = 0; n < ngx_threads_n; n++) {

ngx_threads[n].cv = ngx_cond_init(cycle->log);

if (ngx_threads[n].cv == NULL) {
/* fatal */
exit(2);
}

if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
ngx_worker_thread_cycle,
(void *) &ngx_threads[n], cycle->log)
!= 0)
{
/* fatal */
exit(2);
}
}
}
}
#endif

如果进程里使用多线程的处理方式,调用的是ngx_worker_thread_cycle进行处理。

再看回函数里面,然后函数进入循环,看到循环里面的ngx_process_events_and_timers(cycle);函数,里面就是进程处理各种事件的位置了。进到函数里看到如下代码:

    if (ngx_use_accept_mutex) {
if (ngx_accept_disabled > 0) {
ngx_accept_disabled--;

} else {
if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
return;
}

if (ngx_accept_mutex_held) {
flags |= NGX_POST_EVENTS;

} else {
if (timer == NGX_TIMER_INFINITE
|| timer > ngx_accept_mutex_delay)
{
timer = ngx_accept_mutex_delay;
}
}
}
}

这里是linux2.6以下为了避免“惊群”对accept进行上锁的处理。

得到锁后就进行accept处理,然后释放锁

    if (ngx_posted_accept_events) {
ngx_event_process_posted(cycle, &ngx_posted_accept_events);
}

if (ngx_accept_mutex_held) {
ngx_shmtx_unlock(&ngx_accept_mutex);
}

最后处理各种事件(void) ngx_process_events(cycle, timer, flags);

    if (ngx_posted_events) {
if (ngx_threaded) {
ngx_wakeup_worker_thread(cycle);

} else {
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}
至此,基本能看到nginx的整个网络层大概处理连接的方式,既预分配多个进程同时accept的处理方式。