Nginx源码分析—HTTP框架执行流程

HTTP框架动态执行中的大概流程:先与客户端建立TCP连接,接收HTTP请求行、头部并解析出他们的意义,再根据nginx.conf配置文件找到一些HTTP模块,使其一次合作者处理这个请求。

为了精确地控制超时,还需要把读写事件放置到定时器中。

通过事件模块提东的ngx_handle_read_event方法和ngx_handle_write_event方法,可以把相应的事件添加到epoll中,我们可以起到在满足事件触发条件时,ngxin进程会调用ngx_event_t事件的handler回调方法执行业务。而通过事件模块通过的ngx_add_timer方法可以将上面的读事件或者写事件添加到定时器中,在满足超时条件后,Nginx进程同样会调用调用ngx_event_t事件的Handler回调方法执行业务。

TCP连接建立成功以后,TCP连接上第一次出现可读事件时,将会调用ngx_http_init_request方法初始化这个HTTP请求,HTTP框架并不会在连接建立成功后就开始初始化请求,而是在这个连接的套接字缓冲区傻瓜确实接收到用户发来的请求内容时才进行。

每个HTTP模块都可以针对一个请求设置上下文结构体,并通过ngx_http_set_ctx和ngx_http_get_module_ctx宏来设置和获取上下文,这些HTTP模块针对请求设置的上下文结构体指针,实际上时保存到ngx_http_request_t结构体的ctx指针数组中的。

Ngx_http_core_content_phase是NGX_HTTP_CONTENT_PHASE阶段的checker方法,可以说他是我们开发HTTP模块时最常用的一个阶段,NGX_HTTP_CONTENT_PAHSE阶段用于真正处理请求的内容。其余10个阶段中个HTTP模块的处理方法都是放在全局的ngx_http_core_main_conf_t结构体中的,也就是说,他们对任何一个HTTP请求都是有效的。但在NGX_HTTP_CONTENT_PHASE阶段却是很自然地有另一种需求,有的HTTP模块可能仅今希望在这个处理请求内容的阶段,仅针对某种请求唯一生效,而不是对所有请求生效。例如,仅当请求的URI匹配了配置文件中的某个Locatin块时,再根据Location块下的配置选择一个HTTP模块执行他的Handler处理方法,并以此替代NGX_HTTP_CONTENT_PHASE阶段的其他handler方法(这些handler方法对于该请求将得不到执行),这个方式被设置为ngx_http_core_loc_conf_t中的handler

处理Post请求,调用ngx_http_run_poted_requests方法处理Post请求。

如果一个请求同时需要与多个上游服务器打交道,同时处理多个TCP连接,那么它需要处理的事件就太多了,这种复杂度会使得模块难以维护,通过使用subrequest机制

一个请求通常由必选的HTTP请求行、请求头部、以及可选的包体组成。

Ngx_http_send_header方法负责狗仔HTTP相应行、头部,同时会把他们发送给客户端。他是一个过滤链表,最后一个节点负责发送,就是过滤模块ngx_http_header_filter_modlue提供的ngx_http_header_filter方法则会根据HTTP规则把headers_out中的成员变量序列化为字符流,如果无法一次把相应头发送出去怎么办?这就需要使用ngx_http_request_t结构体中ngx_chain_t类型的成员Out了,它将会保存没有发送完的相应头部,如何发送剩余的相应头部,需要结合结束请求的ngx_http_finalize_request方法来说。

当ngx_http_header_filter方法无法一次性发送HTTP头部时,将会有以下两个现象同时发生,请求的Out成员中将会保存剩余的相应头部,Ngx_http_header_filter方法返回NGX_AGAIN.

如果这个响应没有包体,那么这时通常已经可以调用ngx_http_finalize_request方法来结束请求了,此函数的第二个参数很关键,我们需要把NGX_AGAIN传进去,这样ngx_http_finalize_request方法就理解了实际上还需要HTTP框架继续发送请求Out成员中保存的剩余响应字符流。Ngx_http_finalize_request方法会设置请求的write_event_handler成员为ngx_http_write方法,这样,当连接上有可写事件时,就会调用ngx_http_write方法继续发送剩余的HTTP响应。Ngx_http+finalize_request方法结合第二个参数可以有很多中执行流程。

时间: 2024-10-31 03:18:55

Nginx源码分析—HTTP框架执行流程的相关文章

Netty源码分析之NioEventLoop执行流程

NioEventLoop启动触发条件: 1.服务端绑定本地端口 2.新连接接入通过chooser绑定一个NioEventLoop 服务端绑定本地端口 绑定本地端口,使用下面方法; ChannelFuture future = bootstrap.bind(host, port).sync(); 最终会调用doBind0()方法: private static void doBind0(final ChannelFuture regFuture, final Channel channel, fi

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

nginx源码总结: 1)代码中没有特别绕特别别扭的编码实现,从变量的定义调用函数的实现封装,都非常恰当,比如从函数命名或者变量命名就可以看出来定义的大体意义,函数的基本功能,再好的架构实现在编码习惯差的人实现也会黯然失色,如果透彻理解代码的实现,领悟架构的设计初衷,觉得每块代码就想经过耐心雕琢一样,不仅仅实现了基本的功能给你,为其他人阅读也会提供很好的支持.细致恰当的命名规则就可以看出作者的功力. 2)更好更高的软件性能体现在架构设计上,好的架构会让软件更加稳定.容易维护.便于扩展.从核心模块

nginx源码分析--nginx模块解析

nginx的模块非常之多,可以认为所有代码都是以模块的形式组织,这包括核心模块和功能模块,针对不同的应用场合,并非所有的功能模块都要被用到,附录A给出的是默认configure(即简单的http服务器应用)下被连接的模块,这里虽说是模块连接,但nginx不会像apache或lighttpd那样在编译时生成so动态库而在程序执行时再进行动态加载,nginx模块源文件会在生成nginx时就直接被编译到其二进制执行文件中,所以如果要选用不同的功能模块,必须对nginx做重新配置和编译.对于功能模块的选

nginx源码分析--模块分类

ngx-modules Nginx 主要的模块大致可以分为四类: handler – 协同完成客户端请求的处理.产生响应数据.比如模块, ngx_http_rewrite_module, ngx_http_log_module, ngx_http_static_module. filter – 对 handler 产生的响应数据做各种过滤处理.比如模块, ngx_http_not_modified_filter_module, ngx_http_header_filter_module. ups

Nginx源码分析:3张图看懂启动及进程工作原理

编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由陈科在高可用架构群分享.转载请注明来自高可用架构公众号「ArchNotes」.   导读:很多工程师及架构师都希望了解及掌握高性能服务器开发,阅读优秀源代码是一种有效的方式,nginx 是业界知名的高性能 Web 服务器实现,如何有效的阅读及理解 nginx?本文用图解的方式帮助大家来更好的阅读及理解 nginx 关键环节的实现.   陈科,十年行业从业经验,曾在浙江电信.阿里巴巴.华为.五八同城任开发工程及架构师等职,目前负责河狸

Nginx源码分析 - Nginx启动以及IOCP模型

Nginx 源码分析 - Nginx启动以及IOCP模型 版本及平台信息 本文档针对Nginx1.11.7版本,分析Windows下的相关代码,虽然服务器可能用linux更多,但是windows平台下的代码也基本相似 ,另外windows的IOCP完成端口,异步IO模型非常优秀,很值得一看. Nginx启动 曾经有朋友问我,面对一个大项目的源代码,应该从何读起呢?我给他举了一个例子,我们学校大一大二是在紫金港校区,到了 大三搬到玉泉校区,但是大一的时候也会有时候有事情要去玉泉办.偶尔会去玉泉,但

nginx源码分析之模块初始化

在nginx启动过程中,模块的初始化是整个启动过程中的重要部分,而且了解了模块初始化的过程对应后面具体分析各个模块会有事半功倍的效果.在我看来,分析源码来了解模块的初始化是最直接不过的了,所以下面主要通过结合源码来分析模块的初始化过程. 稍微了解nginx的人都知道nginx是高度模块化的,各个功能都封装在模块中,而各个模块的初始化则是根据配置文件来进行的,下面我们会看到nginx边解析配置文件中的指令,边初始化指令所属的模块,指令其实就是指示怎样初始化模块的. 模块初始化框架 模块的初始化主要

Nginx源码分析—架构设计思想

Nginx源码分析-架构设计思想 我任务nginx的源码可以分为三个部分,一个是在ngx_init_cycle之前,这个也算是为了重新启动nginx而准备的代码,比如说在这个时候可以接受外部的信号,也可以保存传递的参数,等等,当然在以后的函数中也考虑了是否正在重启nginx. 至于ngx_init_cycle这个函数,是一个很庞大的函数,在这个函数中可以看到调用了各个模块的钩子函数,这里又设计到了nginx结构体的使用,比如所有的模块都是ngx_module_t这个结构体,但是这个结构体中的ct

TOMCAT源码分析(启动框架)

建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, 是不那么容易掌握TOMCAT的框架的. 所以得实践.实践.再实践. 建议下载一份TOMCAT的源码, 调试通过, 然后单步跟踪其启动过程. 如果有不明白的地方, 再来查阅本文, 看是否能得到帮助. 我相信这样效果以及学习速度都会好很多! 1. Tomcat的整体框架结构 Tomcat的基本框架, 分为4个层次. Top Level Elements: Server Service Connector HTTP AJP Conta