Nginx如何解决事件过期问题
来源:互联网 发布:利用淘宝双十一赚钱 编辑:程序博客网 时间:2024/05/19 02:28
详细解释请参考《Nginx模块开发与架构解析》的9.6.3节ngx_epoll_module模块的实现
nginx源码如下:
struct ngx_event_s { ...... /* used to detect the stale events in kqueue, rtsig, and epoll */ /* 这个标志位用于区分当前事件是否过期,它仅仅是给事件驱动模块使用的,而事件消费模块可不用关心。 为什么需要这个标志位呢?当开始处理一批事件时,处理前面的事件可能会关闭一些连接,而这些连接有可能影响这批事件中还未处理到的后面的事件。 这时,可通过instance标志位来避免处理后面的已经过期的事件。 */ unsigned instance:1; ......};
static ngx_int_tngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags){ int op; uint32_t events, prev; ngx_event_t *e; ngx_connection_t *c; struct epoll_event ee; c = ev->data; events = (uint32_t) event; if (event == NGX_READ_EVENT) { e = c->write; prev = EPOLLOUT;#if (NGX_READ_EVENT != EPOLLIN) events = EPOLLIN;#endif } else { e = c->read; prev = EPOLLIN;#if (NGX_WRITE_EVENT != EPOLLOUT) events = EPOLLOUT;#endif } if (e->active) { op = EPOLL_CTL_MOD; events |= prev; } else { op = EPOLL_CTL_ADD; } ee.events = events | (uint32_t) flags; ee.data.ptr = (void *) ((uintptr_t) c | ev->instance); //这里利用了指针的最后一位一定是0的特性(因为CPU地址一定是2的倍数),用最后一位保存添加事件时的instance。 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0, "epoll add event: fd:%d op:%d ev:%08XD", c->fd, op, ee.events); if (epoll_ctl(ep, op, c->fd, &ee) == -1) { ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "epoll_ctl(%d, %d) failed", op, c->fd); return NGX_ERROR; } ev->active = 1; return NGX_OK;}
ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log){ ngx_uint_t instance; ngx_event_t *rev, *wev; ngx_connection_t *c; ...... ngx_memzero(rev, sizeof(ngx_event_t)); ngx_memzero(wev, sizeof(ngx_event_t)); rev->instance = !instance; wev->instance = !instance; rev->index = NGX_INVALID_INDEX; wev->index = NGX_INVALID_INDEX; rev->data = c; wev->data = c; wev->write = 1; return c;}
static ngx_int_tngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags){ int events; uint32_t revents; ngx_int_t instance, i; ngx_uint_t level; ngx_err_t err; ngx_event_t *rev, *wev, **queue; ngx_connection_t *c; /* NGX_TIMER_INFINITE == INFTIM */ //一开始就是等待事件,最长等待时间为timer;nginx为事件专门用红黑树维护了一个计时器 events = epoll_wait(ep, event_list, (int) nevents, timer); ...... ngx_mutex_lock(ngx_posted_events_mutex); //循环开始处理收到的所有事件 for (i = 0; i < events; i++) { c = event_list[i].data.ptr; instance = (uintptr_t) c & 1; c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); rev = c->read; //判断事件是否过期 if (c->fd == -1 || rev->instance != 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; } //取得发生一个事件 revents = event_list[i].events; //该事件是一个读事件,并该连接上注册的读事件是active的 if ((revents & (EPOLLERR|EPOLLHUP)) && (revents & (EPOLLIN|EPOLLOUT)) == 0) { /* * if the error events were returned without EPOLLIN or EPOLLOUT, * then add these flags to handle the events at least in one * active handler */ revents |= EPOLLIN|EPOLLOUT; } if ((revents & EPOLLIN) && rev->active) { if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1; } //事件放入到相应的队列中 if (flags & NGX_POST_EVENTS) { queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue); } else { rev->handler(rev); } } wev = c->write; if ((revents & EPOLLOUT) && wev->active) { if (c->fd == -1 || wev->instance != 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; } if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { ngx_locked_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); } } } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK;}
0 0
- Nginx如何解决事件过期问题
- 如何解决MyEclipse过期问题
- 如何解决 OpenQuant 过期的问题
- 如何解决Photoshop CS6试用版过期问题?
- 解决证书过期问题
- 解决smartGit过期问题
- 解决PLSQL过期问题
- 如何简便的解决虚拟机里软件过期问题
- 如何解决MATLAB还有X天过期的问题
- 如何解决chrome flash 过期
- 如何解决Nginx的session一致性问题
- 解决vmware tools过期问题
- 解决ClickOnce签名过期问题
- 解决myeclipse8.6过期问题
- 解决dreamweaver4证书过期问题
- 解决was6版本过期问题
- Navicat过期问题的解决
- 解决AspJpeg组件过期问题
- 关于验证码识别的两种方案
- 安卓事件处理
- ios微秀音乐控制案例
- 一个有意思的拼接数组
- Linux定时器
- Nginx如何解决事件过期问题
- Unity3d GUI与NGUI
- Informatica&DAC
- Java Notes-8
- Quick 3.3中display.newColorLayer的错误
- 史上最简单Robotium跨进程操作实践——基于ADB框架
- 排序专题学习笔记——插入排序
- 《数据结构》课程设计
- 课程设计