资讯专栏INFORMATION COLUMN

Nginx 源码分析:从模块到配置(下)

Chao / 2124人阅读

摘要:每个模块由以下几部分构成结构体代表模块本身,其指针被放入数组中。结构体用来表示模块的配置内容,其中部分成员可以通过配置文件进行配置。调用该中的函数,该函数最终初始化模块对应的结构体,完成配置。因此,分析源码中的配置指令,就是分析结构体。

本篇的上篇 Nginx 源码分析:从模块到配置(上),建议阅读本篇前先阅读上篇。

关于模块

Nginx的架构高度模块化。每个模块各司其职,组合在一起完成特定的功能。

Nginx通过configure决定哪些模块被安装。所有安装的模块在编译阶段静态生成,其指针被统一放入ngx_modules数组中,供全局使用。

每个模块由以下几部分构成:

ngx_module_t结构体:代表模块本身,其指针被放入ngx_modules数组中。

ngx__conf_t结构体:用来表示模块的配置内容,其中部分成员可以通过配置文件进行配置。

ngx__module_t结构体:模块上下文,保存了一组操作,Nginx初始化阶段调用这些操作,初始化ngx__conf_t中的成员。

ngx_command_t结构体数组:该数组中每一项ngx_command_t对应配置文件中一条指令。

Nginx的模块虽然有很多。但是基本类型只有5种:CORF、CONF、EVNT、HTTP、MAIL

#define NGX_CORE_MODULE      0x45524F43  /* "CORE" */
#define NGX_CONF_MODULE      0x464E4F43  /* "CONF" */
#define NGX_EVENT_MODULE     0x544E5645  /* "EVNT" */
#define NGX_HTTP_MODULE      0x50545448  /* "HTTP" */
#define NGX_MAIL_MODULE      0x4C49414D  /* "MAIL" */

每种类型对应一种ngx__module_t上下文结构体。Nginx在初始化(主要在ngx_init_cycle函数中)时根据不同的模块类型,调用不同的上下文中的操作,完成其配置内容的初始化。

虽然模块类型只有5种,但是模块数量可以有很多,每个模块都针对自身有特定的配置内容,这些配置内容中,可以被放到配置文件nginx.conf中的,被包装成了一条条ngx_command_t指令。这些指令的内容决定了nginx.conf中可以写入的操作指令。

Nginx初始化时解析nginx.conf配置文件,找到对应的ngx_command_t。调用该ngx_command_t中的函数,该函数最终初始化模块对应的ngx__conf_t结构体,完成配置。

这就是模块和配置之间的关系。

配置文件、指令

谈到Nginx的配置,首先想到的肯定是配置文件nginx.conf

众所周知,nginx.conf配置文件的结构由一条条Nginx配置指令构成(官方文档)。
Nginx配置指令可以分为两种:简单指令和块指令。

例如:

worker_processes 1;就是一条简单指令

events { ... }就是一条块指令

如果,一个块指令中含有其他指令,那么称这个块指令为上下文(注意区别模块中的上下文概念)。
例如:

 events {
      use epoll;
      worker_connections  1024;
 }

events是块指令,由于events中包含有指令(简单指令或块指令)。因此称eventsevents上下文

常见的上下文还有:http上下文、server上下文、location上下文整个nginx.conf文件称为main上下文

源码中的配置指令

前面提到过:Nginx配置文件中的一条指令对应一个ngx_command_t结构体。因此,分析源码中的配置指令,就是分析ngx_command_t结构体。

ngx_command_t结构体定义:

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;
    ngx_uint_t            offset;
    void                 *post;
};

各成员含义如下:

name:本条指令的名字,例如worker_processes 1;对应的ngx_command_s.name就是worker_processes

set:函数指针,所以set用来表示,当Nginx解析配置文件,碰到指令时,该执行怎样的操作。而该操作本身,自然是用来设置本模块所对应的ngx__conf_t结构体。

conf:这个变量只在NGX_HTTP_MODULE类型的模块的ngx_command_t使用。这个变量和今天讨论的话题关系不大。暂不讨论。

offset:这个变量用来标记ngx__conf_t中某成员变量的偏移量,纯粹是为使用方便。

type:配置指令属性的集合。例如,worker_processes这条指令对应的type定义为:

NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1

其中,各个宏定义如下:

#define NGX_MAIN_CONF        0x01000000
#define NGX_DIRECT_CONF      0x00010000
#define NGX_CONF_TAKE1       0x00000002

NGX_MAIN_CONF是指,该指令用于main上下文

NGX_DIRECT_CONF是指,该指令是用于main上下文的简单指令

NGX_CONF_TAKE1是指,该指令后跟一个参数,例如worker_processes 1;1就是指后面跟一个参数,这个参数的数目由NGX_CONF_TAKE1指定。

类似用来定义指令类型的宏还有很多,具体可以参考源码中各个模块中ngx_command_t的设置。

几个典型的配置指令 daemon指令

Nginx默认是以后台的形式运行的,这种运行形式被称为daemon,当然,在调试的时候,为了方便,一般是关掉daemon这种运行形式。

在配置文件中通过daemon指令来打开或关闭。官方文档对daemon指令说明如下:

Syntax:     daemon on | off;
Default:    daemon on;
Context:    main

在源码中(core ginx.c),daemon指令对应的ngx_command_t结构体如下:

     {ngx_string("daemon"),                              // 指令的名字daemon
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,       // 指令的类型
      ngx_conf_set_flag_slot,                            // 指令对应的操作
      0,
      offsetof(ngx_core_conf_t, daemon),
      NULL }

其中,NGX_MAIN_CONF指,daemon指令的上下文为main上下文
NGX_DIRECT_CONF指,daemon指令是一条可以直接写在main上下文的简单指令。
NGX_CONF_FLAG指,daemon指令是一个开关指令,接收on | off作为指令参数。

user指令

Nginx可以在配置文件中通过user指令指定运行时所在的用户及用户组。官方文档对user指令的说明如下:

Syntax:     user user [group];
Default:    user nobody nobody;
Context:    main

在源码中(core ginx.c),user对应的ngx_command_t结构体定义如下:

    { ngx_string("user"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
      ngx_set_user,
      0,
      0,
      NULL },

其中NGX_MAIN_CONFNGX_DIRECT_CONF的含义与daemon指令的含义相同。
NGX_CONF_TAKE12是指该指令接收1个或两个参数,即Syntax: user user [group];

events指令

Nginx中可以指定采用的事件监听机制类型,比如select、poll、epoll等。
这个指定操作在events指令中完成。这里events指令为块指令

官方文档对events指令的定义如下:

Syntax:     events { ... }
Default:    —
Context:    main

在源码中(event gx_event.c),events指令对应的ngx_command_t结构体定义如下:

    { ngx_string("events"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_events_block,
      0,
      0,
      NULL }

其中,NGX_MAIN_CONF的含义与daemon指令相同。
NGX_CONF_BLOCK是指,这是一条块指令
NGX_CONF_NOARGS是指,该指令不接受参数。

总结

以上三条指令能够很清楚的说明,在Nginx源码中是如何组织和管理配置文件中使用的配置指令的。
对于其他指令,可以直接阅读源码中该指令的定义。源码就是最好的文档。

关于模块和配置的总结

由于Nginx是高度模块化的,因而,Nginx的配置一定是对模块的配置

Nginx的每条配置指令对应某模块中的一条ngx_command_t定义。

每条ngx_command_t一定操作了其所在模块的ngx__conf_t结构体中某些项。

Nginx初始化时,首先解析配置文件,然后执行对应指令的ngx_command_t中的操作函数,设置ngx__conf_t中的某些项,完成配置工作。

然后,Nginx根据这些配置,执行启动流程,进而开始工作。

到此为止。本篇结束。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/39154.html

相关文章

  • Nginx 源码分析模块配置(上)

    摘要:结构体数组,用来表示该模块可以在配置文件中配置的项目,及其操作指令。 源文件路径 srccore gx_conf_file.h srccore gx_conf_file.c 主要内容 本篇的主要目的在于分析Nginx的配置功能。由于Nginx的配置基本就是对模块的配置,因此,在讨论配置功能之前,需要先分析Nginx的模块功能。 对于模块功能,这里的重点不在于某个模块的细节,而...

    gotham 评论0 收藏0
  • Nginx源码分析Nginx配置文件解析(一)

    摘要:本文将从源码从此深入分析配置文件的解析,配置存储,与配置查找。在学习配置文件的解析过程之前,需要先了解一下模块与指令的一些基本知识。 运营研发团队 李乐 配置文件是nginx的基础,对于学习nginx源码甚至开发nginx模块的同学来说更是必须深究。本文将从源码从此深入分析nginx配置文件的解析,配置存储,与配置查找。 看本文之前读者可以先思考两个问题: 1.nginx源码中随处可以...

    JasonZhang 评论0 收藏0
  • Nginx源码分析Nginx的listen处理流程分析

    摘要:四监听套接字的使用假设此处我们使用作为事件处理模块在增加事件时用户可以使用中的字段当事件发生时该字段也会带回。在创建监听套接字时将结构分为级监听套接字地址各级都是一对多的关系。 施洪宝 一. 基础 nginx源码采用1.15.5 后续部分仅讨论http中的listen配置解析以及优化流程 1.1 概述 假设nginx http模块的配置如下 http{ server { ...

    yuanzhanghu 评论0 收藏0
  • 分析Nginx 源码 - ngx_module_t接口总结

    摘要:关于有一套设计良好的源码,以供分析,本文从结构体来分析源码结构。总结初次阅读源码,先从结构体开始学习,开篇之作,再接再厉。 关于 nginx有一套设计良好的源码,以供分析,本文从ngx_module_t结构体来分析nginx源码结构。ngx_module_t是整个nginx的关键,它提供了整个nginx的模块化的基础。因此,看懂ngx_module_t结构体才能开始入门nginx源码阅...

    sunnyxd 评论0 收藏0
  • Nginx源码:利用C语言tricky构建函数链

    摘要:请注意这里的和是全局变量,而和是模块的静态变量是模块级的全局变量,这一点很重要,后面会详细分析。当编译进一个模块的时候,就被赋值为当前模块的处理函数。所以整体看来,就像用全局变量组成的一条单向链表。 最近开始使用Nginx的第三方扩展解决实际的问题,对Nginx的扩展开发产生了一些兴趣,在阅读第三方代码时产生了一些心得和体会。本文详细分析了进行Nginx过滤器开发的时候,Nginx提供...

    wind5o 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<