}
}
}
在此处,会调用ngx_event_core_module的ngx_event_process_init函数。
这个函数(很长,很长)主要做了这么几件事情:
1、处理惊群问题(回头会专门来一篇讲惊群)
2、初始化两个队列,一个用于存放不能及时处理的建立连接事件,一个用于存储不能及时处理的读写事件。
ngx_queue_init(&ngx_posted_accept_events);
ngx_queue_init(&ngx_posted_events);
3、初始化定时器。
4、调用 ngx_epoll_init 。
5、分配连接池空间、读事件结构体数组、写事件结构体数组。
6、为每个监听端口分配连接。
7、为每个监听端口的连接的读事件设置handler,并将每个监听端口的连接的读事件添加到epoll中。
worker 开始循环干活了
ngx_worker_process_cycle 函数(也不是很长,但是我不想放)。
不过这个我可以压缩一下,因为看了好几遍了,没上面那个那么恐怖:
for ( ;; ) {
…
/* 处理IO事件和时间事件 */
ngx_process_events_and_timers(cycle);
…
}
短哈。
在worker的主循环中,所有的事件都是通过函数ngx_process_events_and_timers处理的,那我们自然就要再往下走了嘛,今天我还非要看看它到底是怎么吃一半了再塞回去的!
ngx_process_events_and_timers
这个函数又干了些什么好事儿呢?
1、配置更新时间方式。是吧,原先我是不把定时器当回事儿的,但是这代码到处都是定时器,所以我就把定时器当回事儿了。
2、处理了一下惊群锁的事情。主要思想就是:负载过高咱就不抢,不然赶紧的冲上去。后面讲惊群的时候放这个代码。
3、调用事件处理函数ngx_process_events,epoll使用的是ngx_epoll_process_events函数。这个咱一会儿还得进去。
4、计算ngx_process_events函数的调用时间。
5、处理ngx_posted_accept_events队列的连接事件。这里accept事件的handler为ngx_event_accept。
6、处理定时器事件,具体操作是在定时器红黑树中查找过期的事件,调用其handler方法。
7、处理ngx_posted_events队列的读写事件,即遍历ngx_posted_events队列,调用事件的handler方法。
ngx_epoll_process_events
再坚持一会儿。。。
static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
······
ngx_event_t *rev, *wev;
/* 调用epoll_wait,从epoll中获取发生的事件 */
events = epoll_wait(ep, event_list, (int) nevents, timer);
······
/* 处理epoll_wait返回为-1的情况 */
if (err) {
······
}
/* 若events返回为0,判断是因为epoll_wait超时还是其他原因 */
if (events == 0) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
“epoll_wait() returned no events without timeout”);
return NGX_ERROR;
}
/* 对epoll_wait返回的链表进行遍历 */
for (i = 0; i < events; i++) {
c = event_list[i].data.ptr;
/* 从data中获取connection & instance的值,并解析出instance和connection */
instance = (uintptr_t) c & 1;
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
/* 取出connection的read事件 */
rev = c->read;
/* 判断读事件是否过期 */
if (c->fd == -1 || rev->instance != instance) {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
“epoll: stale event %p”, c);
continue;
}
/* 取出事件的类型 */
revents = event_list[i].events;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
“epoll: fd:%d ev:%04XD d:%p”,
c->fd, revents, event_list[i].data.ptr);
/* 若连接发生错误,则将EPOLLIN、EPOLLOUT添加到revents中,在调用读写事件时能够处理连接的错误 */
if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
“epoll_wait() error on fd:%d ev:%04XD”,
c->fd, revents);
revents |= EPOLLIN|EPOLLOUT;
}
/* 事件为读事件且读事件在epoll中 */
if ((revents & EPOLLIN) && rev->active) {
······
rev->ready = 1;
/* 事件是否需要延迟处理?对于抢到锁监听端口的worker,会将事件延迟处理 */
if (flags & NGX_POST_EVENTS) {
/* 根据事件的是否是accept事件,加到不同的队列中 */
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
[外链图片转存中…(img-6hGUA7KL-1711804414600)]
[外链图片转存中…(img-gZfIiMNa-1711804414600)]
[外链图片转存中…(img-55LRwFa0-1711804414600)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!