IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Nginx事件模块学习之定时器 -> 正文阅读

[系统运维]Nginx事件模块学习之定时器

??????? Nginx中对事件处理的定时器是利用红黑树实现的,下来逐步分析一下nginx如何对定时器实现的。

??????? 首先,Nginx的工作进程是一个无限for循环,主要代码如下:

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 就是处理事件的函数。再这之前我们需要了解 ngx_event_timer_init 函数,该函数在工作进程初始化 ngx_worker_process_init 在初始化事件模块时调用的,具体函数如下:

ngx_int_t ngx_event_timer_init(ngx_log_t *log)
{
    // 初始化定时器事件的红黑树
    ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
                    ngx_rbtree_insert_timer_value);

    return NGX_OK;
}

????????添加事件至事件树上其函数为: ngx_event_add_timer,主要代码如下:

static ngx_inline void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
{

	// 当前时间 + 定时时间,计算出将来的某一超时时刻
    key = ngx_current_msec + timer;

	……

    ev->timer.key = key;

    // 将事件添加至事件的红黑树上
    ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->timer);

    ……
}

??????? 查询事件树上timer最小的函数为:ngx_event_find_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;
    }

    root = ngx_event_timer_rbtree.root;
    sentinel = ngx_event_timer_rbtree.sentinel;

    node = ngx_rbtree_min(root, sentinel);

    timer = (ngx_msec_int_t) (node->key - ngx_current_msec);

    return (ngx_msec_t) (timer > 0 ? timer : 0);
}

??????? 了解了上述三个函数,下来分析一下工作进程循环里的ngx_process_events_and_timers函数,主要代码如下:

void ngx_process_events_and_timers(ngx_cycle_t *cycle)
{
	……
    // 为epoll的wait提供一个超时时间,以防止epoll的wait阻塞时间太长
	timer = ngx_event_find_timer();
    ……

	// 调用 epoll_wait 去监听并处理读写事件
    (void) ngx_process_events(cycle, timer, flags);

    ……
    if (delta) {
        ngx_event_expire_timers();
    }
	……
}

??????? 上述代码中每次for循环开始都会查找事件树中最小超时事件的时间,将该时间作为epoll_wait函数的超时时间,以防止epoll_wait函数阻塞时间过长。后续的 delta 变量为执行ngx_event_expire_timers函数的时间,如果该时间超过1ms则事件树上有可能有事件到期,则遍历事件树执行到期时间的handler并移除该过期事件,函数为ngx_event_expire_timers,主要代码如下:

void ngx_event_expire_timers(void)
{
	……
    for ( ;; ) {
		……
		
		// 找出最小key值的
        node = ngx_rbtree_min(root, sentinel);

		// 如果最小的key对于的事件没过期则返回 
        if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) {
            return;
        }

        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
		
		……
		// 删除刚才找出的事件节点
        ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

		……
		// 执行事件的回调函数
        ev->handler(ev);
    }
}

??????? 执行完ngx_event_expire_timers后一次for循环就算是执行完了,后续一直循环执行就可以。至此,nginx的工作进程定时器处理事件的也算是整个完了。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-30 12:50:22  更:2021-10-30 12:51:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:50:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码