zoukankan      html  css  js  c++  java
  • nginx学习 timer

    想好好啃啃nginx的代码。已经将网上容易找到的nginx源码分析系列粗略过了一遍,也开发过几个简单的nginx-module,接下来想要提升一个档次只能自己来啃代码了。

    //source: /src/event/ngx_event_timer.c

    timer负责事件相关的计时功能,时间存储在一个RB-tree(红黑树)。【Tengine团队将rb-tree改为四叉最小堆,并声称有10%以上的性能提升,期待并后续学习】

    static ngx_rbtree_node_t          ngx_event_timer_sentinel;  //定义一个全局的rbtree根节点,该根节点只起到一个哨兵作用,不存具体的值
    struct ngx_rbtree_node_s {  //红黑树节点的六个值
         ngx_rbtree_key_t       key;
         ngx_rbtree_node_t     *left;
         ngx_rbtree_node_t     *right;
         ngx_rbtree_node_t     *parent;
         u_char                 color;
         u_char                 data;
    };

    再来认识一下ngx_rbtree_s

    struct ngx_rbtree_s {
         ngx_rbtree_node_t     *root;      //根节点
         ngx_rbtree_node_t     *sentinel;  //哨兵节点,即NIL节点,空节点
         ngx_rbtree_insert_pt   insert;    //插入回调函数句柄
    };

    在接下来的ngx_event_timer_init中调用了ngx_rbtree_init初始化这个rbtree,这里rbtree相关的操作在 /src/core/ngx_rbtree.c实现。

    ngx_event_find_timer完成查找时间功能:从rbtree中找出最小时间,并计算与当前时间之差。查找timer,返回距离最近超时事件的时间,若有事件超时则返回0。

    ngx_msec_t
    ngx_event_find_timer(void)
    {
        ngx_msec_int_t      timer;
        ngx_rbtree_node_t  *node, *root, *sentinel;
    
        if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {   //根节点为空
            return NGX_TIMER_INFINITE;  //返回无限,即无时间限制
        }
    
        ngx_mutex_lock(ngx_event_timer_mutex); //对rbtree操作需要加锁
    
        root = ngx_event_timer_rbtree.root;
        sentinel = ngx_event_timer_rbtree.sentinel; 
    
        node = ngx_rbtree_min(root, sentinel); //获取rb-tree中的最小节点
    
        ngx_mutex_unlock(ngx_event_timer_mutex); //解锁
    
        timer = (ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec; //最小值-当前时间,当该值大于0即表明没有需要处理的超时事件
    
        return (ngx_msec_t) (timer > 0 ? timer : 0);  
    
    }
    接下来一个主要的函数是ngx_event_expire_timers(void),这个函数不接收任何参数,也没有返回值。这个函数的功能是处理rb_tree中所有超时事件。
    void
    ngx_event_expire_timers(void)
    {
        ngx_event_t *ev;
        ngx_rbtree_node_t *node, *root, *sentinel;
    
        sentinel = ngx_event_timer_rbtree.sentinel;
    
        for ( ;; ) {  //无限循环
    
        ngx_mutex_lock(ngx_event_timer_mutex);
    
        root = ngx_event_timer_rbtree.root;
    
        if (root == sentinel) {   //空树处理
             return;
        }
    
        node = ngx_rbtree_min(root, sentinel); //找到最小时间点
    
        /* node->key <= ngx_current_time */
    
        if ((ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec <= 0)  //小于0代表这个key已经超时了
        {
            ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));  //offsetof 算的是timer在ngx_event_t结构体中的偏移量,ev是通过node找到对应的事件
            //这里ev的原理:node为结构体ngx_event_t的一个变量,通过指针往回移动偏移量的大小,就能将指针指向ngx_event_t的开头,即指向事件的开头。
    
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                "event timer del: %d: %M",
                ngx_event_ident(ev->data), ev->timer.key);    //ngx_event_ident 是从event的data部分获取其connection信息。
    
            ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);  //将找到的事件对应的timer从rbtree中删除
    
            ngx_mutex_unlock(ngx_event_timer_mutex);
    
            ev->timer_set = 0;
    
            ev->timedout = 1;  //表明超时了
    
            ev->handler(ev);  //调用超时的回调函数进行事件处理
    
            continue;  //再取下一个超时待处理事件
         }
    
       break;   //没有找到超时需要处理的事件,就退出返回了
    }

    好了,只有短短几十行代码的分析。其它的下回分解。

  • 相关阅读:
    ORACLE NOLOGGING研究
    由2013星光大道总决赛同步程序猿怎样成功?
    configure: error: mysql configure failed. Please check config.log for more information.
    The 2014 ACM-ICPC Asia Mudanjiang Regional Contest(2014牡丹江区域赛)
    about service in android
    极客标签互动课程系列 - Javascript生成SVG动画素描特效
    sql -- 移除数据中的换行符和回车符
    前端project师必需知识点
    spring装配集合
    【java项目实践】具体解释Ajax工作原理以及实现异步验证username是否存在+源代码下载(java版)
  • 原文地址:https://www.cnblogs.com/xiaohuo/p/2555056.html
Copyright © 2011-2022 走看看