栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

nginx 源码分析

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

nginx 源码分析

nginx采用的master进程创建listen,work进程accept的方式是《unix网络编程》中的预派生进程阻塞在accept的方式。并且书中说明这种问题有惊群问题,可以前面加文件锁或者线程锁互斥

在Linux2.6版本以后,内核内核已经解决了accept()函数的“惊群”问题,大概的处理方式就是,当内核接收到一个客户连接后,只会唤醒等待队列上的第一个进程或线程。所以,如果服务器采用accept阻塞调用方式,在最新的Linux系统上,已经没有“惊群”的问题了

原理图可以参考:linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。 - DeNiro - 博客园

事件模块的初始化就发生在ngx_worker_process_init函数中。

其调用关系:main() ---> ngx_master_process_cycle() ---> ngx_start_worker_processes() ---> ngx_spawn_process() ---> ngx_worker_process_cycle() ---> ngx_worker_process_init()。

static ngx_int_t
ngx_event_process_init(ngx_cycle_t *cycle)
{
    ......
    
    if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
        ngx_use_accept_mutex = 1;
        ngx_accept_mutex_held = 0;
        ngx_accept_mutex_delay = ecf->accept_mutex_delay;
 
    } else {
        ngx_use_accept_mutex = 0;
    }
  
    ngx_queue_init(&ngx_posted_accept_events);
    ngx_queue_init(&ngx_posted_events);
    
    if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
        return NGX_ERROR;
    }
    
    for (m = 0; cycle->modules[m]; m++) {
        ......
 
        if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
            exit(2);
        }
 
        break;
    }
 
    
    if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
        ......
        sa.sa_handler = ngx_timer_signal_handler;
        sigemptyset(&sa.sa_mask);
 
        if (sigaction(SIGALRM, &sa, NULL) == -1) {
            ......
        }
 
        itv.it_interval.tv_sec = ngx_timer_resolution / 1000;
        ......
 
        if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
            ......
        }
    }
 
    ......
 
    
    cycle->connections =
        ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
    ......
 
    c = cycle->connections;
 
    
    cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
                                   cycle->log);
    ......
 
    rev = cycle->read_events;
    for (i = 0; i < cycle->connection_n; i++) {
        rev[i].closed = 1;
        rev[i].instance = 1;
    }
 
    
    cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
                                    cycle->log);
    ......
 
    wev = cycle->write_events;
    for (i = 0; i < cycle->connection_n; i++) {
        wev[i].closed = 1;
    }
 
    
    i = cycle->connection_n;
    next = NULL;
 
    do {
        i--;
         
        
        c[i].data = next;
        c[i].read = &cycle->read_events[i];
        c[i].write = &cycle->write_events[i];
        c[i].fd = (ngx_socket_t) -1;
 
        next = &c[i];
    } while (i);
 
    
    cycle->free_connections = next;
    cycle->free_connection_n = cycle->connection_n;
     
    
    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {
 
        ......
 
        c = ngx_get_connection(ls[i].fd, cycle->log);
 
        ......
 
        rev = c->read;
 
        ......
 
        
        rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept
                                                : ngx_event_recvmsg;
                                  
        
        ......
        if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
            return NGX_ERROR;
        }
 
    }
 
    return NGX_OK;
}
  • (1)打开accept_mutex负载均衡锁,用于防止惊群。惊群是指当多个worker都处于等待事件状态,如果突然来了一个请求,就会同时唤醒多个worker,但是只有一个worker会处理该请求,这就造成系统资源浪费。为了解决这个问题,nginx使用了accept_mutex负载均衡锁。各个worker首先会抢锁,抢到锁的worker才会监听各个端口。
  • (2)初始化两个队列,一个用于存放不能及时处理的建立连接事件,一个用于存储不能及时处理的读写事件。
  • (3)初始化定时器,该定时器就是一颗红黑树,根据时间对事件进行排序。
  • (4)调用使用的ngx_epoll_module的ctx的actions的init方法,即ngx_epoll_init函数。该函数较为简单,主要的作用是调用epoll_create()和创建用于存储epoll_wait()返回事件的链表event_list。
  • (5)如果再配置中设置了timer_resolution,则要设置控制时间精度,用于控制nginx时间。这部分在第五部分重点讲解。
  • (6)分配连接池空间、读事件结构体数组、写事件结构体数组。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/361240.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号