第4章 配置、error日志和请求上下文

在开发功能灵活的Nginx模块时,需要从配置文件中获取特定的信息,不过,不需要再编写一套读取配置的系统,Nginx已经为用户提供了强大的配置项解析机制,同时它还支持"-s reload"命令——在不重启服务的情况下可使配置生效。4.1节会回顾第2章中http配置项的一些特点,4.2节中会全面讨论如何使用http配置项,包括使用Nginx预设的解析方法(可以少写许多代码)或者自定义配置项的解析方式,如果读者对其中较复杂的配置块嵌套关系有疑问,在4.3节中会从HTTP框架的实现机制上解释http配置项的模型。

开发复杂的Nginx模块时,如何定位代码上的问题是必须考虑的前提条件,此时输出各种日志就显得很关键了,4.4节中会讨论Nginx为用户准备好的输出日志方法。

编写全异步的HTTP模块时,必须要有上下文来维持一个请求的必要信息,在4.5节中,首先探讨请求的上下文与全异步实现的Nginx服务之间的关系,以及如何使用HTTP上下文,然后简单描述HTTP框架是如何管理请求的上下文结构体的。

4.1 http配置项的使用场景

在第2章中通过多样化修改nginx.conf文件中的配置项,实现了复杂的Web服务器功能。其中,http{……}内的配置项最为复杂,在http配置块内还有server块、location块等,同一个配置项可以同时出现在多个http块、server块或location块内。

那么,如何解析这样的配置项呢?在第3章中的mytest例子中,又是怎样获取nginx.conf中的配置的呢?当同一个配置在http块、server块、location块中同时出现时,应当选择哪一个块下的配置呢?当多个不同URI表达式下的location都配置了mytest这个配置项,然而后面的参数值却不同时,Nginx是如何处理的呢?这些就是本章将要回答的问题。

我们先来看一个例子,有一个配置项test_str,它在多个块内都出现了,如下所示。


http{

test_str main;

server{

listen 80;

test_str server80;

location/url1{

mytest;

test_str loc1;

}

location/url2{

mytest;

test_str loc2;

}

}

server{

listen 8080;

test_str server8080;

location/url3{

mytest;

test_str loc3;

}

}

}


在上面的配置文件中,test_str这个配置项在http块内出现的值为main,在监听80端口的server块内test_str值为server80,该server块内有两个location都是由第3章中定义的mytest模块处理的,而且每个location中又重新设置了test_str的值,分别为loc1和loc2。在这之后又定义了监听8080端口的server块,并重定义test_str的值为server8080,这个server块内定义的一个location也是由mytest模块处理的,而且这个location内再次重定义了test_str的值为loc3。(事实上不只是例子中的server块可以嵌套location块,location块之间还可以继续嵌套,这样test_str的值就更复杂了,上例中没有出现location中进一步反复嵌套location的场景。在4.3.3节讨论HTTP框架如何合并配置项时涉及了location块的反复嵌套问题,请读者注意。)

在这段很短的配置中,mytest模块将会处理两个监听端口上建立的TCP连接,以及3种HTTP请求,请求的URL分别对应着/url1、/url2、/url3。假设mytest模块必须取出test_str配置项的参数,可是在以上的例子中test_str出现了6个不同的参数值,分别为main、server80、server8080、loc1、loc2、loc3,那么在mytest模块中我们取到的test_str值以哪一个为准呢?

事实上,Nginx的设计是非常灵活的(实际上这是第10章将要介绍的HTTP框架设计的),它在每一个http块、server块或location块下,都会生成独立的数据结构来存放配置项。因此,我们允许当用户访问的请求不同时(如请求的URL分别是/url1、/url2、/url3),配置项test_str可以具有不同的值。那么,当请求是/url1时,test_str的值应当是location块下的loc1,还是这个location所属的server块下的server80,又或者是其所属http块下的值main呢?完全由mytest模块自己决定,我们可以定义这个行为。下面在4.2节中将说明如何灵活地使用配置项,在4.3节中将探讨Nginx实际上是如何实现http配置功能的。