Nginx源代码分析—业务流程

到此为止,我们如果ngx_init_cycle已经结束。我们临时无论他做了什么,我们从他做的效果进入。

从常理上来讲,假设一个请求到达,那么我们须要接受这个请求,那么就从请求来介绍!

在ngx_event_process_init函数中将监听套接字上的读事件注冊为ngx_event_accept,ngx_event_accept是为了接受请求的,它负责接收一个连接,那么连接接收完毕以后直接调用这个监听套接字上的处理函数ls->handler(c);那么这个时候是怎么处理的呢?他是怎样被赋值的呢?

这就须要ngx_init_cycle中的已经调用过的函数。ngx_http_block(事实上ngx_event_process_init也是在ngx_init_cycle解析配置文件事被调用的)。

Ngx_http_block函数内容非常丰富,解析配置。初始化一些东西,到了最后:ngx_http_optimize_servers



ngx_http_optimize_servers这个就是进入一些回调的注冊ngx_http_init_listening。从函数的名字是为了初始化监听套接字。



ngx_http_add_listening函数是创建一个监听套接字。并对这个监听套接字进行初始化。这个监听套接字(ngx_listening_t类型)上的handler被赋值为ngx_http_init_connection



ngx_http_init_connection函数初始化一个连接。接受完以后就是调用这个来初始化一个连接,同一时候将这个连接上的读写时间的回调赋值

rev = c->read;

rev->handler = ngx_http_wait_request_handler;//连接上读事件回调

c->write->handler = ngx_http_empty_handler;//连接上的写事件的回调 这个为空,在開始仅仅有读事件。

ngx_http_wait_request_handler函数整将创建一个请求结构体,c->data = ngx_http_create_request(c);

同一时候rev->handler = ngx_http_process_request_line; //将读事件赋值为此并直接调用此函数

ngx_http_process_request_line(rev);



 ngx_http_process_request_line(rev)中须要ngx_http_parse_request_line解析请求行,假设没有解析成功,说明请求行还没有读完,所以读事件上的回调还是这个。假设解析成功,

rev->handler = ngx_http_process_request_headers;//读事件上的回调为请求头

ngx_http_process_request_headers(rev);



ngx_http_process_request_headers(rev);函数中也是一个死循环,直到读取头部信息完整才结束,读取结束以后就解析ngx_http_parse_header_line。解析头部信息,解析完毕以后就处理头信息ngx_http_parse_header_line。处理结束就ngx_http_process_request,处理请求。



ngx_http_process_request,这个函数进入了http请求中的11个阶段,这个nginx为Http请求来设计的

c->read->handler = ngx_http_request_handler;

    c->write->handler = ngx_http_request_handler;

   r->read_event_handler = ngx_http_block_reading;

  ngx_http_handler(r);

   ngx_http_run_posted_requests(c);

这几个函数都非常重要。连接上的读写事件都是ngx_http_request_handler,然而请求上的读事件回调为ngx_http_block_reading。首先说下流程



ngx_http_request_handler函数中就是依据发生了读写事件中的哪个,转而调用了该请求上记录的write_event_handler或者read_event_handler。接下来调用ngx_http_run_posted_requests.



在ngx_http_handler函数中将请求上的写回调write_event_handler记录为ngx_http_core_run_phases。接下来就是调用ngx_http_core_run_phases这个函数,



ngx_http_core_run_phases这个函数就是进入了11个阶段。刚開始感觉很奇怪。

到此为止。HTTP请求流程结束。



至于ngx_http_run_posted_requests函数。是由于这个请求上可能有多个子请求,子请求直接使用请求上的write_event_handler函数处理





有几点须要解说一下。

Epoll模型监控的是读写事件。是ngx_event_t结构体。是一个连接(ngx_connection_t结构体)中的ngx_event_t对象。也即是ngx_connectin_t中的read&write字段。

在ngx_http_request_handler函数中将读写事件进行了转移,转移到了请求中的read_event_handler和write_event_handler回调。

请求中的read_event_handler和write_event_handler函数存在的原因是什么呢?

为了请求的转移,每个请求都须要记住自己走到了哪个步骤,而不是epoll中注冊的读写事件回调,Nginx须要全程非堵塞,自己处理到某个阶段须要自己记录,等到自己再进行处理,就能够接着处理了也即是从接收到一个完整的请求以后,进入11个阶段的处理后,处理的流程须要请求自己掌控,这也是异步的思想,那么一个请求处理完一个阶段。什么时候计入下一个阶段呢,有定时器激活。





要明确一点就是,事件结构体(ngx_event_t)中的data域是ngx_connection_t结构体,

Ngx_connection_t结构体中的data域是请求结构体(ngx_http_request_t),请求中的connection相应着这个请求相应的一个连接。连接上的读写事件(ngx_event_t)是epoll监听的对象

Nginx源代码分析—业务流程的更多相关文章

  1. 新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t

    新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...

  2. 新秀nginx源代码分析数据结构篇(两) 双链表ngx_queue_t

    nginx源代码分析数据结构篇(两) 双链表ngx_queue_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...

  3. nginx源代码分析--进程间通信机制 & 同步机制

    Nginx源代码分析-进程间通信机制 从nginx的进程模型能够知道.master进程和worker进程须要通信,nginx中通信的方式有套接字.共享内存.信号.对于master进程,从外部接受信号, ...

  4. nginx源代码分析之内存池实现原理

    建议看本文档时结合nginx源代码. 1.1   什么是内存池?为什么要引入内存池? 内存池实质上是接替OS进行内存管理.应用程序申请内存时不再与OS打交道.而是从内存池中申请内存或者释放内存到内存池 ...

  5. nginx源代码分析--从源代码看nginx框架总结

    nginx源代码总结: 1)代码中没有特别绕特别别扭的编码实现.从变量的定义调用函数的实现封装,都非常恰当.比方从函数命名或者变量命名就能够看出来定义的大体意义,函数的基本功能,再好的架构实如今编码习 ...

  6. nginx源代码分析--配置文件解析

    ngx-conf-parsing 对 Nginx 配置文件的一些认识: 配置指令具有作用域,分为全局作用域和使用 {} 创建其他作用域. 同一作用域的不同的配置指令没有先后顺序:同一作用域能否使用同样 ...

  7. nginx源代码分析--模块分类

    ngx-modules Nginx 基本的模块大致能够分为四类: handler – 协同完毕client请求的处理.产生响应数据.比方模块, ngx_http_rewrite_module, ngx ...

  8. nginx源代码分析--读请求主体(1)

    首先,读取请求体已进入HTTP要求11相,我们需要做的请求正文部分处理一些模块,所以这个模块需要注册功能在这个阶段,在阅读功能要求的身体ngx_http_read_client_request_bod ...

  9. nginx源代码分析--框架设计 & master-worker进程模型

    Nginx的框架设计-进程模型 在这之前,我们首先澄清几点事实: nginx作为一个高性能server的特点.事实上这也是全部的高性能server的特点,依赖epoll系统调用的高效(高效是相对sel ...

随机推荐

  1. 分析iOS Crash文件,使用命令符号化iOS Crash文件

    TBMainClient.ipa改名为TBMainClient.zip并解压得到TBMainClient.app 然后将TBMainClient.app      TBMainClient.app.d ...

  2. redis实现秒杀demo

    代码 package com.prosay.redis; import java.util.List; import redis.clients.jedis.Jedis; import redis.c ...

  3. 在websocket中怎么样注入service类

    最近项目中用到了websocket,遇到很多问题,其中一个是@ServerEndpoint修饰的类无法注入其他的bean,注入的对象都是null,在网上找了好多资料,无意中发现一个朋友的答案给了思路. ...

  4. Eclipse启动时提示Fail to create the Java Virtual Machine的解决方法

    这个错误是Eclipse里面的一个bug,我们通过如下的设置就可以解决它. 打开eclipse安装目录下的eclipse.ini文件: 将其中的256m改为128m,512m改为256m,1024m改 ...

  5. HTML5 Geolocation API地理定位整理(一)

    HTML5 Geolocation API 用于获得用户的地理位置. 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的. 浏览器支持 Internet Explorer 9+, ...

  6. 【BZOJ】【3930】【CQOI2015】选数

    数论/莫比乌斯反演/快速mu前缀和 比较容易想到令f[x]表示gcd=x的方案数,令g[x]表示x|gcd的方案数. 那么有$ g(d)=\sum_{d|n} f(n)$,根据莫比乌斯反演,有$f(d ...

  7. Qt解决:Qobject::connect queue arguments of type ‘xxxx’,Make sure ‘xxxx’ is registered using qRegister

    解决方法:在调用connect之前,通过 qRegisterMetaType() 注册你connect函数里对象的类型代码如下: typedef QString CustomString;//你自己定 ...

  8. [转]使用HackCube-Special分析胎压传感器信号

    胎压无线传感器安全检测 我们团队之前也有用USRP和GNUradio对其他的胎压设备进行的安全检测,我不使用这套环境的原因是软件无线电的设备和笔记本已经算体积不小的一套设备,通常测试环境都在户外,在这 ...

  9. go语言之进阶篇WriteString的使用

    1.WriteString的使用 示例: package main import ( "fmt" "os" ) func WriteFile(path stri ...

  10. jQuery EasyUI Datagrid性能优化专题(转)

    jQuery  EasyUI的Datagrid组件功能算是很强大了,不过性能确实不怎么乐观,而对于性能问题,网络上几乎也找不到相关的优化资料,所谓的牛人们可能 都望而却步了.本博客以后会带着分析Dat ...