文档章节

nginx源码分析——http处理流程

hncscwc
 hncscwc
发布于 2016/07/15 21:29
字数 992
阅读 315
收藏 6
点赞 0
评论 2

1. http处理流程概述

nginx对于http请求处理的大概流程是:接收客户端发起的连接,然后接收并解析http请求行,接收并解析http头部;再根据配置文件nginx.conf找到相关http模块,使这些模块依次合作处理http请求,最后发送http响应并结束http请求。

在整个http请求处理过程中,nginx通过连接的读写事件,以及定时器机制,异步回调完成其处理流程。

2. http新连接的建立

事件模块一文中我们知道,当新连接建立后会回调对应侦听的处理方法。对于http模块,该回调方法为ngx_http_init_connection。在该方法中,主要完成的事情是:设置连接的读事件回调处理方法为ngx_http_wait_request_handler,设置连接的写事件回调处理方法为ngx_http_empty_handler;然后查看读事件是否已经准备好,即连接对应的套接字缓冲区上是否已经接收到用户的请求数据了,如果是,则直接调用ngx_http_wait_request_handler进入下一处理步骤;如果还没有准备好,则对连接的读事件设置定时器,同时将读事件添加到事件驱动中,等待下一次回调处理。

void ngx_http_init_connection(ngx_connection_t *c)
{
    ...
    // 设置读写事件回调处理方法
    rev = c->read;
    rev->handler = ngx_http_wait_request_handler;
    c->write->handler = ngx_http_empty_handler;

    if( rev->ready ) {
        if( ngx_use_accept_mutex ) {
            ngx_post_event(rev, &ngx_posted_events);
            return;
        }
        // 事件已经准备好, 直接处理
        rev->handler(rev);
        return;
    }

    // 设置定时器
    ngx_add_timer(rev, c->listening->post_accept_timeout);
    ngx_reusable_connection(c, 1);

    // 将读事件加入事件驱动中
    if(ngx_handle_read_event(rev, 0) != NGX_OK) {
        ngx_http_close_connection(c);
        return;
    }
}

3. 首次可读事件的处理

当连接对应的套接字缓冲区首次接收到用户的请求数据后,会回调ngx_http_wait_request_handler方法,在该函数中,会调用recv接收用户的请求数据,同时创建一个ngx_http_request_t用于本次http请求处理,然后调用ngx_http_process_request_line开始处理http请求行。

static void ngx_http_wait_request_handler(ngx_event_t *rev)
{
    ....
    // 接收数据
    n = c->recv(c, b->last, size);
    if( n == NGX_AGAIN ) {
        if(!rev->timer_set) {
            ngx_add_timer(rev, c->listening->post_accept_timeout);
            ngx_reusable_connection(c, 1);
        }
        if( ngx_handle_read_event(rev,0) != NGX_OK ) {
            ngx_http_close_connection(c);
            return ;
        }
    }
    if(n == NGX_ERROR ) {
        ngx_http_close_connection(c);
        return ;
    }

    ....
    
    // 创建request
    c->data = ngx_http_create_request(c);
    if(c->data == NULL) {
        ngx_http_close_connection(c);
        return ;
    }
    rev->handler = ngx_http_process_request_line;
    ngx_http_post_request_line(rev);
}

4. http请求行/http头部的接收处理

在完成了请求的初始化后,会依次调用ngx_http_process_request_line和ngx_http_process_request_headers方法开始接收http请求行和http头部,并解析出URL,请求方法等各字段的含义。当这些都处理完成后,调用ngx_http_process_request进入请求真正的处理阶段。

static void ngx_http_process_request_line(ngx_event_t * rev)
{
    ....
    for( ;; ) {
        // 解析 http行
        rc = ngx_http_parse_request_line(r, r->header_in);
        if( rc == NGX_OK ) {
            // 处理http uri
            if(ngx_http_process_request_uri(r) != NGX_OK) {
                return ;
            }

            // 设置连接的读事件回调处理, 并开始处理http请求的头部
            rev->handler = ngx_http_process_request_headers;
            ngx_http_process_request_headers(rev);
            return ;
        }
    }
}

static void ngx_http_process_request_headers(ngx_event_t * rev)
{
    ....
    rc = NGX_AGAIN;
    for( ;; ) {
        if( rc == NGX_AGAIN ) {
            n = ngx_http_request_header(r);
        }

        // 解析http的头部
        rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers);
        if( rc == NGX_HTTP_PARSE_HEADER_DONE) {
            r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
            // 处理http的头部
            rc = ngx_http_process_request_header(r);
            if(rc != NGX_OK) {
                return ;
            }
            // 开始http请求的处理
            ngx_http_process_request(r);
            return ;
        }
    }
}

5. http请求的处理

在ngx_http_process_request中,将连接读写事件的回调处理均设置为ngx_http_request_handler方法,然后调用ngx_http_handler,而在ngx_http_handler中最终调用ngx_http_core_run_phases开始http的多阶段处理。

void ngx_http_process_request(ngx_http_request_t *r )
{
    ....
    c->read->handler = ngx_http_request_handler;
    c->write->handler = ngx_http_request_handler;
    c->read_event_handler = ngx_http_block_reading;
    ngx_http_handler(r);
    ngx_http_run_posted_requests(c);
}

void ngx_http_handler(ngx_http_request_t * r)
{
    ...
    // 开始http请求的多阶段处理
    r->write_event_handler = ngx_http_core_run_phases;
    ngx_http_core_run_phases(r);
}

6. 发送http请求响应

http请求响应回复一般会通过ngx_http_send_header发送http头部,通过ngx_http_output_filter发送http的包体。ngx_http_send_header和ngx_http_output_filter都是由一系列的filter模块组成,这些模块对响应数据进行加工处理,最终调用ngx_http_write_filter进行数据的发送。

ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
{
    ....
    return ngx_http_top_header_filter(r);
}

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ....
    rc = ngx_http_top_body_filter(r, in);
    ....
}

7. 结束http请求

一般来讲,结束http请求会调用ngx_http_finalize_request来完成。到这里,整个http的处理流程结束。

© 著作权归作者所有

共有 人打赏支持
hncscwc
粉丝 64
博文 66
码字总数 76137
作品 0
杭州
程序员
加载中

评论(2)

hncscwc
hncscwc

引用来自“摩云飞”的评论

改行专攻nginx了?
有个项目需要,就研究下
摩云飞
摩云飞
改行专攻nginx了?
nginx源码分析—启动流程

作者:阿波 本文链接:http://blog.csdn.net/livelylittlefish/article/details/7243718 Content 0. 序 1. main()分析 2. 注意问题 2.1 几个初值 2.2 nginx工作模式 2.3 一些配置 2.4 其他开...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

nginx源码分析——模块

模块介绍 高度模块化的设计是nginx的架构基础。在nginx中,除了少量的核心代码,其他一切皆为模块。这种模块化设计同时具有以下几个特点: 高度抽象的模块接口 所有的模块都遵循着同样的 ng...

hncscwc ⋅ 2016/06/17 ⋅ 0

nginx源码分析——配置

配置介绍 nginx的配置由一个主配置文件和其他一些辅助的配置文件构成。这些配置文件均是纯文本文件,这些配置文件全部位于nginx安装目录下的conf目录中。 主配置文件nginx.conf中的内容大概是...

hncscwc ⋅ 2016/06/13 ⋅ 0

nginx源码分析——http多阶段处理

多阶段处理概述 nginx将一个http请求分为顺序的多个处理阶段,前一个阶段的结果会影响后一个阶段的处理。例如,ngxhttpaccess_module模块根据IP信息拒绝一个用户请求后,本应接着执行的其他H...

hncscwc ⋅ 2016/07/04 ⋅ 0

nginx源码分析——事件模块

事件模块概述 事件处理框架所要解决的问题是如何收集,管理,分发事件。这里所说的事件,主要以网络事件和定时器事件为主,而网络事件中又以TCP网络事件为主。由于网络事件与网卡中断处理程序...

hncscwc ⋅ 2016/06/23 ⋅ 0

Laravel源码分析——一次Http请求到响应

1前言 在FastCGI协议下工作的php-fpm, 使用持续的进程来处理一连串的请求, 具体到某个请求的解析流程的时候, 如果不考虑扩展的方式, 基本上都是顺序的解析处理. 所以就算复杂如Laravel框架,...

hisense20112784 ⋅ 2017/08/22 ⋅ 0

《深入探索Netty原理及源码分析》文集小结

写在2017年末尾,翻看文集的第一篇文章已经是三个月前的事了,也没想过这文集会写那么久,这么慢。。。 Netty文集中的文章主要都是我学习过程的笔记,写博客的主要目的是为了通过输出来倒逼输...

tomas家的小拨浪鼓 ⋅ 2017/12/30 ⋅ 0

nginx源码分析—hash结构ngx_hash_t(v1.0.4)

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(阿波)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.hash结构 1.1ngxhasht结构 1.2ngxhashinit_t结构 1....

晨曦之光 ⋅ 2012/03/09 ⋅ 0

libevent源码深度剖析

作者:http://blog.csdn.net/sparkliang/article/category/660506 libevent源码深度剖析十三——libevent信号处理注意点 2010-02-11 20:00阅读(1669)评论(6) libevent源码深度剖析PDF 2010-...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

Node.js 中遇到含空格 URL 的神奇“Bug”——小范围深入 HTTP 协议

首先声明,我在“Bug”字眼上加了引号,自然是为了说明它并非一个真 Bug。 1. 问题抛出 昨天有个童鞋在看后台监控的时候,突然发现了一个错误: 大概意思就是说:一台服务器通过 HTTP 协议去...

死月絲卡蕾特 ⋅ 2017/12/13 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 今天 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部