Nginx处理流程

  1. worker进程获取互斥accept锁(如果有配置开启互斥锁)
  2. accept
  3. 非阻塞recv,如果socket读缓冲区有数据则直接读取,否则添加读事件至事件池(红黑树)
  4. 进入 epoll/select 中断处理流程
  5. NGX_HTTP_POST_READ_PHASE(读取请求内容阶段)
  6. NGX_HTTP_SERVER_REWRITE_PHASE(server级别的uri重写阶段)
  7. NGX_HTTP_FIND_CONFIG_PHASE(寻找location配置阶段,该阶段使用重写之后的uri来查找对应的location,因为location级别可能有重写指令所以可能会被执行多次)
  8. NGX_HTTP_REWRITE_PHASE(location级别的uri重写阶段,该阶段执行location基本的重写指令,也可能会被执行多次)
  9. NGX_HTTP_POST_REWRITE_PHASE(location级别重写的最后处理阶段)
  10. NGX_HTTP_PREACCESS_PHASE(访问权限控制的前一阶段,该阶段在权限控制阶段之前,一般用于访问控制)
  11. NGX_HTTP_ACCESS_PHASE(访问权限控制阶段)
  12. NGX_HTTP_POST_ACCESS_PHASE(访问权限控制的最后处理阶段)
  13. NGX_HTTP_PRECONTENT_PHASE(开始内容生成前的阶段)
  14. NGX_HTTP_CONTENT_PHASE(内容生成阶段,该阶段产生响应,并发送到客户端)
  15. NGX_HTTP_LOG_PHASE(日志记录阶段)

epoll处理流程

  1. socket->bind->listen->epoll_create->epoll_ctl->epoll_wait进入阻塞等待接收数据
  2. 网卡把接收到的数据写至内存
  3. 网卡向CPU发送中断信号
  4. CPU通过网卡中断程序处理数据(给eventpool就绪队列添加socket引用,唤醒等待队列中的程序)
  • 就绪列表(rdlist 双向链表,对接收到数据socket的引用,便于程序快速查找有数据的socket)
  • 监视列表(rbr 红黑树,用于保存需要监听的socket)
  • 等待队列(wq,程序执行epoll_wait后添加进程的引用至eventpool等待队列,阻塞程序)

select处理流程

  1. socket->bind->listen->accept->recv进入阻塞等待接收数据
  2. 网卡把接收到的数据写至内存
  3. 网卡向CPU发送中断信号
  4. CPU通过网卡中断程序处理数据(将数据写入socket接收缓冲区、唤醒对应socket等待队列中的进程)

每次select都需要将进程加入所有监视socket的等待队列

每次唤醒都需要从每个待执行队列中移除

每次恢复执行都需要遍历是哪个socket收到数据

  • 工作队列(内核空间中的待CPU调度进程)
  • 等待队列(添加进程的引用至等待队列)
  • socket(发送缓冲区、接收缓冲区、等待队列)