nginx网络层分析

本文深入分析了高性能开源HTTP服务器Nginx的源代码,重点探讨了其网络层的连接处理机制,包括多进程与多线程的并发处理方式,以及如何高效地进行accept操作和事件处理。

近来有空阅读了一下高性能开源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的处理方式。





Nginx 提供了强大的负载均衡能力,同时内置的 `upstream` 功能结合 `proxy_pass`, `load_balancer`, `keepalive` 和 `timeout` 参数可以实现多种类型的负载均衡和流量分配。其中,四层健康检查是针对底层TCP/IP协议层的连接状态进行检查的一种方法,主要用于验证后端服务器的物理链路是否通畅、端口是否开放等基本连通性信息。然而,Nginx本身并没有直接提供四层的健康检查机制,它侧重于应用层的健康检查和负载均衡。 Nginx的健康检查通常是基于七层HTTP协议的,用于验证后端服务是否能正常响应HTTP请求,比如通过发送一个简单的GET请求并检查返回的状态码是否在预设范围内(通常为2xx)。这对于Web服务来说是至关重要的,因为它确保了后端服务能够正确处理HTTP请求并且返回有效的响应。 ### 实现四层健康检查的一般做法 由于Nginx自身并不直接支持四层健康检查,实现这一功能通常需要依赖以下几个步骤: 1. **使用系统命令或脚本进行检查**: - **Ping检查**:通过ping命令快速检查目标服务器的可达性。 - **Telnet或SSH**:通过telnet或SSH登录到后端服务器,简单地检查服务器是否在线并能够接受并返回连接。 - **自定义脚本**:创建或利用现有的脚本来进行更复杂的检查,比如检查端口的打开情况、读写权限等。 2. **通过第三方服务**: - 利用云服务提供商(如AWS、Azure、Google Cloud等)提供的监控和健康管理工具,它们通常提供了全面的网络层和应用层健康检查解决方案。 - 第三方API或服务,如Prometheus、Nagios等,用于收集和分析Nginx后端服务器的健康状况信息。 3. **Nginx的自定义实现**: - 编写自定义的Nginx模块或插件,专门用于四层健康检查。这需要较为高级的技术知识,包括熟悉C语言和了解Nginx模块开发流程。 ### 示例:利用第三方服务实现四层健康检查 假设我们使用Prometheus作为监控工具,可以设置一个告警规则来检查Nginx后端服务器的端口状态。Prometheus的规则文件可以定义检查特定端口是否响应的标准,如果端口无法建立连接超过一定次数,则触发告警。 这样的集成不仅实现了四层的健康检查,而且可以实时监控服务器的状态变化,一旦发现异常可以立即通知运维团队采取措施。 --- 综上所述,尽管Nginx自身并未直接提供四层健康检查功能,但通过组合使用系统命令、第三方服务或自定义实现,仍然可以在Nginx环境下有效管理服务器的物理连通性和应用状态,从而保证整个系统的稳定性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值