什么是过期事件

对于不需要加入到 post 队列 延后处理的事件,nginx 的事件都是通过 ngx_epoll_process_events 函数进行处理的

举例:假如 epoll_wait 一次性返回 3 个事件,在第一个事件关闭了一个连接对应的正好是第三个事件的连接,第二个事件 accept 了一个连接,正好使用的是第二个事件的文件描述符

如图所示:

那么如果仅仅判断是否使用的同一个描述符或者描述符是否被置为 -1,就不能判断是否是同一个连接

上面的这个问题,称之为事件过期问题

nginx 是如何处理过期事件的?

nginx 中的指针的最后一位一定是 0 ,于是,nginx 就使用这最后一位用来表示是否过期

深入理解nginx中,第9章中有一句:利用指针的最后一位一定是0的特性。能解释一下这个特性?

看下面代码中取出与判断 instance 位的操作

nginx 会在每次 accept 一个连接的时候,将 instance 位取反,那么只需要判断 instance 位是否一直就能判断事件是否过期了

// nginx-1.9.2/src/core/ngx_connection.c
// ngx_get_connection
instance = rev->instance; ngx_memzero(rev, sizeof(ngx_event_t));
ngx_memzero(wev, sizeof(ngx_event_t)); rev->instance = !instance;
wev->instance = !instance
// nginx-1.9.2/src/event/modules/ngx_epoll_module.c
// ngx_epoll_process_events
//遍历本次epoll_wait返回的所有事件
for (i = 0; i < events; i++) { //和ngx_epoll_add_event配合使用
/*
对照着上面提到的ngx_epoll_add_event方法,可以看到ptr成员就是ngx_connection_t连接的地址,但最后1位有特殊含义,需要把它屏蔽掉
*/
c = event_list[i].data.ptr; //通过这个确定是那个连接 instance = (uintptr_t) c & 1; //将地址的最后一位取出来,用instance变量标识, 见ngx_epoll_add_event /*
无论是32位还是64位机器,其地址的最后1位肯定是0,可以用下面这行语句把ngx_connection_t的地址还原到真正的地址值
*/ //注意这里的c有可能是accept前的c,用于检测是否客户端发起tcp连接事件,accept返回成功后会重新创建一个ngx_connection_t,用来读写客户端的数据
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); rev = c->read; //取出读事件 //注意这里的c有可能是accept前的c,用于检测是否客户端发起tcp连接事件,accept返回成功后会重新创建一个ngx_connection_t,用来读写客户端的数据 if (c->fd == -1 || rev->instance != instance) { //判断这个读事件是否为过期事件
//当fd套接字描述符为-l或者instance标志位不相等时,表示这个事件已经过期了,不用处理
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: stale event %p", c);
continue;
} // 还有代码,但是不贴这么多了
......
}

那么你可能也跟我有一样的疑问,如果是下面两种情形怎么办?



这样 instance 位又成了 1,那 e 事件处理的岂不是 3 连接的事件了,这样过期事件并没有解决啊

首先,第二张图片中的情况不可能存在,因为 epoll 中的事件是有顺序的,c 事件必然是再 e 事件之后

那么第一张图片中的情况还是没有解决过期事件啊

于是我就翻阅很多资料(主要靠百度)

看到有人遇到过这个疑问:

nginx中事件模型中instance变量的处理细节

如果觉得上面文章太长可以看我的讲解:

意思呢就是

nginx accept 连接之后,会立刻将连接放到 post 延迟处理队列中,不会出现 accept 之后立刻 close 的情况

于是呢,nginx 就完美的解决了事件过期的情况

参考资料

《深入理解 Nginx》

深入理解nginx中,第9章中有一句:利用指针的最后一位一定是0的特性。能解释一下这个特性?

nginx中事件模型中instance变量的处理细节

github 项目:reading-code-of-nginx-1.9.2

nginx 是如何处理过期事件的?的更多相关文章

  1. Windows 下Redis的部署 及key 过期事件

    window下Redis部署,下载安装完成之后,进入到redis目录: 1.修改配置文件redis.windows.service.conf配置密码 requirepass myRedis (注意在R ...

  2. 如何利用redis key过期事件实现过期提醒

    https://blog.csdn.net/zhu_tianwei/article/details/80169900 redis自2.8.0之后版本提供Keyspace Notifications功能 ...

  3. redis中key过期事件

    刚到新公司一个月左右,有个新需求,想做定时任务,比如在用户注册时间的3天后推送用户一条消息. 从刚开始脑子里面闪现的数据库轮询,立马否定掉(浪费资源),再到linux系统的定时任务,但是当用户量过大时 ...

  4. redis过期事件

    背景:目前在商城项目,订单有过期逻辑,小伙伴提议用redis做,经讨论分析,redis有key的过期事件,貌似可以实现,但是咨询大神,好像不建议这样用,可能会丢数据 随便写了段python代码测试 i ...

  5. redis过期事件回调函数,与有序集合

    https://cloud.tencent.com/developer/article/1347437  python中的Redis键空间通知(过期回调) set notify-keyspace-ev ...

  6. Redis Key过期事件

    解决方案1: 可以利用redis天然的key自动过期机制,下单时将订单id写入redis,过期时间30分钟,30分钟后检查订单状态,如果未支付,则进行处理但是key过期了redis有通知吗?答案是肯定 ...

  7. 恶劣的网络环境下,Netty是如何处理写事件的?

    更多技术分享可关注我 前言 前面,在Netty在接收完新连接后,默认为何要为其注册读事件,其处理I/O事件的优先级是什么?这篇文章,分析到了Netty处理I/O事件的优先级——读事件优先,写事件仅仅是 ...

  8. Spring整合redis实现key过期事件监听

    打开redis服务的配置文件   添加notify-keyspace-events Ex  如果是注释了,就取消注释 这个是在以下基础上进行添加的 Spring整合redis:https://www. ...

  9. nginx用指针的值的最后一位来判断过期事件

    nginx中,将地址的最后一位取出来,用Instace变量标识,用来判断是否连接已经被释放成为过期时间 为什么指针地址最后一位一定是0呢? 这里的内存地址,一定是内存分配器分配出来的地址,如new . ...

随机推荐

  1. python 3 字典

    字典,是可变的无序集合,同时是一种以键值对为基本元素的可以存储各种数据类型的集合,用大括号({})表示字典的开始和结束,元素之间用(,)分隔. 键值对,由键(Key)和值(Value)组成,中间用冒号 ...

  2. 乔悟空-CTF-i春秋-Web-SQL

    2020.09.05 是不是有些题已经不能做了--费了半天,到最后发现做不出来,和网上大神的方法一样也不行,最搞笑的有个站好像是别人运营中的,bug好像被修复了-- 做题 题目 题目地址 做题 尝试简 ...

  3. [LeetCode]547. 朋友圈(DFS)

    题目 班上有 N 名学生.其中有些人是朋友,有些则不是.他们的友谊具有是传递性.如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友.所谓的朋友圈,是指所有朋友的集 ...

  4. 送命题:讲一讲Mybatis插件的原理及如何实现?

    持续原创输出,点击上方蓝字关注我吧 目录 前言 环境配置 什么是插件? 如何自定义插件? 举个栗子 用到哪些注解? 如何注入Mybatis? 测试 插件原理分析 如何生成代理对象? 如何执行? 总结 ...

  5. spring boot 源码之banner

    Banner 使用Spring Boot启动的jar包总是会显示一个Spring的图标.实际我们是可以自定义这个图标.Banner接口定义了打印banner的方法. void printBanner( ...

  6. 面向对象技术-原文转载自jingwhale

    面向对象技术 --原文转载自jingwhale,文章底部附原文链接 对象是面向对象的程序设计的核心,它由描述状态的属性(变量)和用来实现对象行为的方法(函数)组成,完成了从数据模型到处理模型的结合与统 ...

  7. msf学习笔记

    metasploit frame 这是一个渗透测试框架,围绕这个框架,我们就可以完成最终的目标,即渗透测试. 渗透测试者困扰:需要掌握数百个工具,上千条命令参数,很难记住. 新出现的漏洞PoC/EXP ...

  8. 几个超级好用但很少有人知道的 webstorm技巧

    我总结一些我发现的比较实用的功能,内容来自日常工作中用到的功能.图片来自PPT,是在公司内部的分享. 你不知道的webstorm进阶使用技巧 1.双击shift 全局搜索,可以搜索代码.设置等. 如果 ...

  9. 渗透测试之信息收集(Web安全攻防渗透测试实战指南第1章)

    收集域名信息 获得对象域名之后,需要收集域名的注册信息,包括该域名的DNS服务器信息和注册人的联系方式等. whois查询 对于中小型站点而言,域名所有人往往就是管理员,因此得到注册人的姓名和邮箱信息 ...

  10. Docker系列——利用gogs搭建属于自己的git服务

    gogs简介 Gogs的目标是打造一个最简单.最快速和最轻松的方式搭建自助Git服务.使用Go语言开发使得Gogs能够通过独立的二进制分发,并且支持Go语言支持的所有平台,包括 Linux.Mac O ...