nginx的启动流程和接客流程

巧了我就是萌 提交于 2020-04-02 09:30:10

  把这些日子看nginx的一些笔记整理了下,准备放在这里,发现越整理越大,这次有些比较粗糙,下次按照各个模块在细化下

主要是两部分,诞生准备接客流程,和接客服务流程。为了清晰点,这里只分析单进程的nginx,对于多个工作进程的nginx模式,这里暂时不讨论。

 

诞生准备接客流程

   nginx的这个小baby诞生前的初始化工作若干,这里的小baby特指建立的ngx_cycle_t,nginx服务的生命周期用到的核心组件都在它里面

  • 设置错误信息存储的buffer

    ngx_strerror_init

 

  • 从启动的命令中获取参数,赋予相应的变量

    ngx_get_options(argc, argv)

-p 赋值给ngx_prefix

ngx的工作目录

 

-c 赋值给ngx_conf_file

nginx的配置文件

 

-g 赋值给ngx_conf_params

nginx的指令

 

-s 赋值给ngx_signal

传递给nginx的信号


  • 时间配置

    ngx_time_init();

 

  • 正则配置

    ngx_regex_init();

 

  • 初始化我们的log,在这之后我们才可以把信息打入我们的日志。

    log = ngx_log_init(ngx_prefix);

 

   nginxbaby的诞生,这个小baby还比较白痴,目前就是个空白,叫init_cycle

 

  • 创建init_cycle,类型为ngx_cycle_t,这个类型相当nbnginx服务的生命周期用到的核心组件都在它里面,然后用ngx_cycle指向init_cycle

 

  • 补充营养,把成长所需的属性给他加上,加上各种魔法属性。

设置相关的系统运行时可以调用的环境变量,把argc,argv,environ处理后赋值给ngx_argc,ngx_argv,ngx_os_argv,ngx_os_environ

ngx_save_argv(&init_cycle, argc, argv)

 

我们把刚才说的nbinit_cycle配置相关的属性。

把ngx_prefix赋值给 init_cycle-> conf_prefix,  init_cycle-> prefix

把ngx_conf_file赋值给 init_cycle-> conf_prefix,  init_cycle-> conf_file

把ngx_conf_params赋值给 init_cycle-> conf_param

    ngx_process_options(&init_cycle)

 

  • 初始化系统变量

    ngx_os_init(log)

 

  • 这个crc32table暂时先忽略吧,对我们的核心大局影响不大。

    ngx_crc32_table_init()

 

  • 这个是对NGX_CHANGEBIN_SIGNAL信号的处理才用的,一般用于老的nginx已经退休了,又启动了一个新的,原来老的子进程要接受这个后爸的过程,获取系统变量 NGINX_VAR,把它赋值给 init_cycle -> listening,并把它的句柄设置为socket句柄

      ngx_add_inherited_sockets(&init_cycle)

      ngx_set_inherited_sockets(cycle)

 

  • 为ngx_modules设置index,这个是方便以后对ngx_modules的引用

 

  • 这个是nginx的核心部分,这个baby的各种nb装备和配置将在这个阶段进行

    初始化cycle,这里面ngx_init_cycle(&init_cycle)

    这个简要说明下,后续有时间要再好好整理下。

 

1 设置cycle的若干属性

paths,open_files,shared_memory,listening,conf_ctx,hostname

 

2 遍历ngx_modules,提取类型为NGX_CORE_MODULE的模块,依次执行

rv = ctx -> create_conf(cycle)。这个是为他们各种初始化属性,也就是给核心模块必要的实体属性,让他们诞生。

我们的NGX_CORE_MODULE的模块还是比较稀有的,目前有

ngx_core_module

ngx_events_module

ngx_http_module

ngx_errlog_module

ngx_mail_module

 

3 建立ngx_conf_t类型的conf,这个conf作为nginx的核心conf

ngx_memzero(&conf, sizeof(ngx_conf_t));

 

4 指令解析,解析完了这个cycle就有了强大的小宇宙,一下子把events,http这里面的所有模块装载上了。

nginx命令行传过来的指令和conf文件传过来的指令进行解析,主要是

调用ngx_conf_parse对三类指令进行解析。

 parse_file

 parse_block

  parse_param

最终应该到会转成parse_param

parse_block为对大括号的块进行解析

Parse_file为对文件进行解析

Parse_param为对一个单一指令进行解析

这里说明下,处理到htttp指令时,ngx_http_block会对配置中的每一个服务器端口建立类型为ngx_listening_s的监听对象,后续在准备接客时,就是对该端口的句柄进行监听,来判断是否有请求到来。

 

5 对于我们的核心模块,根据指令解析结果进行赋值和其他初始化操作

module->init_conf

 

   这个时候终于修成正果了,开始做准备接客的服务,我们启动一个单进程的nginx,daemon给设置成off,把ngx_process设置成   ngx_single_process_cycle,这个可以通过配置nginx.conf来完成

 

daemon off;

master_process off;

  • 信号接收服务

     如果ngx_signal 不为空 调用 ngx_signal_process(cycle, ngx_signal) ,对信号进行处理

 

  • 跟操作系统相关的特殊设置

     ngx_os_specific_status

 

  • 初始化信号

    ngx_init_signals

 

  • daemon的配置

调用ngx_daemon,当然如果我们调试nginx或者阅读分析源码,建议把daemonoff

if (!ngx_inherited && ccf->daemon),启用ngx_daemon,在后台运行

 

  • Ngx_process的配置

如果 ngx_process == NGX_PROCESS_SINGLE 调用 ngx_single_process_cycle(cycle);

否认调用 ngx_master_process_cycle(cycle);

同样为了理解源码需要,建议把ngx_process设置成NGX_PROCESS_SINGLE

 

   时刻准备着接客

接收浏览器的请求,通过ngx_single_process_cycle来完成(当然这个对单进程来说,这里先不分析多个工作进程的情况)。

nginx的每个加载的模块,执行init_process(这里不光光是NGX_CORE_MODULE),对event模块进行init_process时,非常重要的一点是把各个端口对应的句柄加入到事件响应的处理句柄。用来响应客户端的请求

ngx_modules[i]->init_process,

 

然后阻塞到ngx_process_events_and_timers(cycle);由于我们的nginx使用的是epoll网络模式,他会调用ngx_epoll_process_events,这个函数会不断的对浏览器发来的请求进行处理,给出响应的html

 

 nginx启动流程图

 

 

 

 

 

 

 

接客流程:

 

当浏览器发成我要你给我服务的信息时,首先会在一个监听句柄上得到响应,这块是在ngx_epoll_process_events实现的,接到响应后,获取连接句柄,加入读写相关的处理函数句柄,调用

ngx_http_init_request ,http_process_request_line,  ngx_http_process_request_headers对请求进行处理,然后根据相应的phase_engine执行相应的功能,例如rewriteaccess等,最后执行各种filter,发送给我们的客户端。


nginx接客流程图

 

 额,文章最后我们可以看到一个接客的栈,这个是我用gdb截取的,由于nginx源码被我改的乱七八糟了,栈里面的行号大家忽略把

栈信息:

 

#0  ngx_http_gzip_body_filter (r=0x810ba60, in=0x7ffff7f97b30) at src/http/modules/ngx_http_gzip_filter_module.c:477#1  0x0000000000442a33 in ngx_http_postpone_filter (r=0x810ba60, in=0x7ffff7f96810)    at src/http/ngx_http_postpone_filter_module.c:82#2  0x0000000000442fe2 in ngx_http_ssi_body_filter (r=0x8, in=0xffffffffffffffff)    at src/http/modules/ngx_http_ssi_filter_module.c:392#3  0x0000000000446e55 in ngx_http_charset_body_filter (r=0x8, in=0x7ffff7f96810)    at src/http/modules/ngx_http_charset_filter_module.c:552#4  0x00000000004070c1 in ngx_output_chain (ctx=0x810cbc8, in=0x7ffff7f96810) at src/core/ngx_output_chain.c:65#5  0x000000000042f46d in ngx_http_copy_filter (r=0x810ba60, in=0x7ffff7f97b30) at src/http/ngx_http_copy_filter_module.c:141#6  0x000000000043d529 in ngx_http_range_body_filter (r=0x8, in=0x7ffff7f96810)    at src/http/modules/ngx_http_range_filter_module.c:551#7  0x0000000000422f05 in ngx_http_output_filter (r=0x8, in=0x7ffff7f96810) at src/http/ngx_http_core_module.c:1871#8  0x000000000043c799 in ngx_http_static_handler (r=0x810ba60) at src/http/modules/ngx_http_static_module.c:255#9  0x0000000000427799 in ngx_http_core_content_phase (r=0x810ba60, ph=0x8123cd0) at src/http/ngx_http_core_module.c:1365#10 0x00000000004254d6 in ngx_http_core_run_phases (r=0x810ba60) at src/http/ngx_http_core_module.c:854#11 0x00000000004255d3 in ngx_http_handler (r=0x8) at src/http/ngx_http_core_module.c:836#12 0x00000000004267be in ngx_http_internal_redirect (r=0x810ba60, uri=<value optimized out>, args=<value optimized out>)    at src/http/ngx_http_core_module.c:2496#13 0x000000000043d11e in ngx_http_index_handler (r=0x810ba60) at src/http/modules/ngx_http_index_module.c:264#14 0x0000000000427799 in ngx_http_core_content_phase (r=0x810ba60, ph=0x8123ca0) at src/http/ngx_http_core_module.c:1365#15 0x00000000004254d6 in ngx_http_core_run_phases (r=0x810ba60) at src/http/ngx_http_core_module.c:854#16 0x00000000004255d3 in ngx_http_handler (r=0x8) at src/http/ngx_http_core_module.c:836#17 0x000000000042bb2e in ngx_http_process_request (r=0x810ba60) at src/http/ngx_http_request.c:1668#18 0x000000000042c39b in ngx_http_process_request_headers (rev=0x810c550) at src/http/ngx_http_request.c:1102#19 0x000000000042c8b0 in ngx_http_process_request_line (rev=0x811ac18) at src/http/ngx_http_request.c:897#20 0x0000000000429f83 in ngx_http_init_request (rev=0x811ac18) at src/http/ngx_http_request.c:520#21 0x000000000041f84e in ngx_epoll_process_events (cycle=<value optimized out>, timer=<value optimized out>,    flags=<value optimized out>) at src/event/modules/ngx_epoll_module.c:641#22 0x000000000041895a in ngx_process_events_and_timers (cycle=0x8105e70) at src/event/ngx_event.c:248#23 0x000000000041d7b0 in ngx_single_process_cycle (cycle=0x8105e70) at src/os/unix/ngx_process_cycle.c:312#24 0x000000000040453e in main (argc=1, argv=<value optimized out>) at src/core/nginx.c:413

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!