nginx学习笔记六(Nginx事件框架处理流程)

来源:互联网 发布:ubuntu安装firefox命令 编辑:程序博客网 时间:2024/05/15 23:45

之前粗略阅读过《Unix网络编程》,这本教材里面是基于底层的Socket  API实现了一些多进程/多线程模式简单的tcp server。Nginx在linux环境下的底层实现肯定也是基于这些基本的socket API做的,但是这些socket API函数都藏在代码的海洋里,需要花些功夫才能将思路给理清楚。接下来整理整理nginx源码中的这些socket API被调用的位置,并且对相应Nginx的事件框架处理流程做一下梳理。

一.最基本的TCP server的程序结构

最基本的TCP server的程序流程如下:

socket ()---->bind()---->listen()----->进入一个无限的循环

在循环中重复:accept()------->recv/write()。

二.Nginx中对应的函数入口

socket() bind() listen() -----------》 ngx_open_listening_sockets()------------》ngx_init_cycle()----------->main.c
如上所示,nginx在启动之后(创建子进程之前)会解析配置文件,把它需要监听的端口加入listening数组。然后针对配置文件中表明需要监听的每个端口做好bind listen这些初始化操作。

worker进程----------->ngx_event_process_init()----------> ngx_add_event()  这些函数是在初始化的时候将监听事件的fd句柄在epoll中进行注册,并且注册其handler(如果不加accept_mutex互斥锁)

worker进程------------>ngx_process_events_and_timers()---------->ngx_trylock_accept_mutex(cycle)----------》ngx_add_event 如果 加了accept_mutex互斥锁,那么只有在进程抢到互斥锁之后才会加监听事件的句柄在epoll中进行注册

worker进程------------>ngx_process_events_and_timers()---------->ngx_process_events()
使用epoll作为事件驱动时候,ngx_process_events也就对应着ngx_epoll_process_events,这里面会调用epoll-wait来取得已经注册好的并且有数据的事件。然后会调用该事件自身的handler来处理或者加入post队列暂缓处理。读事件的handler--ngx_event_accept中会最终调用accept()系统函数来接受请求。

三.Nginx的事件驱动的特性

1.解决“惊群问题”
本书的作者(阿里陶辉)给出的分析解释很漂亮,可以参见博客:http://blog.csdn.net/russell_tao/article/details/7204260
简单地说,抢互斥锁失败的代价要小于被epoll_wait唤醒但是却抢不到accept代价。所以使用进程互斥锁技术来解决“惊群问题”


2.负载均衡
nginx采用的负载均衡策略很简单,就是每个进程都维护一个ngx_accept_disabled变量,用来表示当前进程处理的连接数目是否超过阈值。如果超过阈值,那么当前进程就不会再去接受新连接。



0 0
原创粉丝点击