本文对Nginx进行了基本介绍,并描述了一些可以使用它完成的简单任务。假设已经安装了Nginx,如果没有,请参阅“Nginx-简介”。本博文介绍了如何启动和停止Nginx以及重新加载其配置,解释了配置文件的结构,并描述了如何设置Nginx以提供静态内容,如何将Nginx配置为代理服务器以及如何将其与FastCGI应用程序相连接。
启动、停止和重新加载配置
nginx -s <signal>
signal
可以是以下信号之一:
- stop: 快速关机
- quit: 正常关机
- reload: 重新加载配置文件
- reopening: 重新打开日志文件
如果要停止Nginx进程,等待工作进程完成当前请求,可以执行以下命令:
nginx -s quit
在诸如kill应用程序等Unix工具的帮助下,也可以向Nginx进程发送信号。在这种情况下,一个信号被直接发送到指定进程ID的进程。Nginx主进程的ID在默认情况下,被写入在/usr/local/nginx/logs
或者/var/run
目录下的nginx.pid
文件当中。如果Nginx的主进程ID为1628,要发送退出信号,优雅的关闭Nginx,我们可以这样:
nginx -s QUIT 1628
配置文件的结构
Nginx
由模块组成,模块由配置文件中指定的指定控制。指令分为简单指令和块指令。一个简单的指令由名称和参数组成,用空格分割,以分号结束。块指令具有与简单指令相同的结构,但不是分号,而是一组由大括号包围的附加指令。如果一个块指令可以在大括号中包含其他指令,那么它被称为上下文(例如:events、http、server和location)
任何放置在上下文外部的配置文件中的指令被认为是在主上下文中。events
和http
指令驻留在主上下文中,server
驻留在http
当中,location
驻留在server
当中。
其中“#”后面都代表是注释内容
顶级上下文有:
- events: 处理常规连接
- http: http请求
- mail: 邮件
- stream: TCP和UDP
在每个http
上下文中,都包含一个或多个server
块来定义控制请求处理的虚拟服务器。对于http
上下文,每个server
指令控制对特定域或IP地址上的资源请求的处理。每个server
上下文中包含一个或多个location
块来处理特定的Uri集。对于mail
或者stream
上下文,server
指令分别控制到达特定TCP端口或UNIX套接字的通信处理。
通常子上下文继承父上下文中包含的指令的设置。一些指令可以出现在多个上下文当中,在这种情况之下,子上下文中的指令会覆盖父上下文中的同名指令。
提供静态内容
Web服务器的一项重要任务是分发文件。首先,我们先做一些准备工作,创建/user/image
目录,并放置一个favorite.png
图片。接下来,我们来修改一下/etc/nginx/sites-enabled
目录下的default
文件(此文件安装Nginx完后存在),在server
上下文中添加一个location
块指令,如下:
location /image/ {
root /user;
}
修改保存之后,重启Nginx。对于匹配的请求,会将URL添加到root
指定指定的路径,即添加到/user
中,形成/user/image/
就是我们本地文件系统上所请求文件的路径。我们在浏览器中访问http://localhost/image/favorite.png
就能正确定位到图片了!如果有多个location
块,将匹配前缀最长的的那个!其中root
指令指定目录!
如果某些功能无法正常工作,你可以查看/var/log/nginx/access.log
或/var/log/nginx/error.log
文件来查找原因!
设置简单的代理服务器
Nginx的一个常见用法是将其设置为代理服务器,这意味着服务器接收请求,将其传递给代理服务器,从代理服务器检索响应并将其发送给客户机。我们将配置一个基本的代理服务器,它使用本地目录中的文件夹来处理图像请求,并将所有请求发送到服务器中。在本例中,这两个服务器定义在一个Nginx实例中,如下:
server {
listen 8080;
root /user/data;
location / {
index index.html;
}
}
这是一个简单的服务器,它监听端口8080(如果没有指定listen
指令,将默认监听80端口),并将所有的请求映射到本地文件系统上的/user/data
目录。需先创建该目录,并将index.html
文件放置在该目录当中,否则请求将会引发404错误!
注意,当服务请求的location
块不包含root
指令时,就会使用上下文中的root
指令!
下面,我们将修改一下配置,将成为代理服务器配置,如下:
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
}
location /image/ {
root /user;
}
}
在第一个location
块中,使用proxy_pass
指令与参数中的协议、代理服务器的名称和端口放在一起。我们还可以对location
做一些正则匹配,如下:
location ~ \.(png|jpg|gif)$ {
root /user;
}
如此,请求匹配所有以.gif
、.jpg
和.gif
结尾的Uri。正则表达式的前面应该加上~
,表示将使用正则表达式进行匹配!
设置FastCGI代理
Nginx可用于将请求路由到FastCGI
服务器,FastCGI
服务器运行各种框架和编程语言(如PHP)构建的应用程序。使用FastCGI
服务器最基本的Nginx配置包括使用fastcgi_pass
指令替代proxy_pass
指令,使用facgi_param
指令设置传递给FastCGI
服务器的参数。假设FastCGI
服务器可以在localhost:9000
上访问。以上一节中的代理配置为基础,将fastcgi_pass
指令替代proxy_pass
指令,并将参数更改为localhost:9000
。在PHP中,SCRIPT_FILENAME
参数用于确定脚本,QUERY_STRING
参数用于传递请求参数。配置如下:
server {
location / {
fastcgi_pass localhost:8080;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(png|jgp|gif)$ {
root /user;
}
}
这将设置一个服务器,通过FastCGI
协议将静态图像请求外的所有请求路由到localhost:9000
上运行的代理服务器!
基于名称的虚拟服务器
Nginx
首先确定哪个服务器应处理该请求,让我们从一个简单的配置开始,下面三个虚拟服务器都在监听80端口,如下:
server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
}
server {
listen 80;
server_name example.com www.example.com;
}
在上面配置当中,Nginx
只检测请求的标头字段“Host”以确定将请求路由到哪个服务器。如果其值与任何服务器都不匹配,或者请求根本不包含此标头字段,则Nginx
会将请求路由到该端口的默认服务器。在上面的配置当中,默认服务器是第一个服务器,这是Nginx
的标准默认行为。也可以在listen
指令中使用default_server
参数设置哪个服务器应该是默认的,如下:
server {
listen 80 default_server;
server_name example.net www.example.net;
}
值得注意的是,default_server
是侦听端口的属性,而不是服务器名称的属性。自0.8.21版本以来,default_server
就可以使用了,但是在更早的版本前,应使用default
参数
如何防止未定义的服务器名称处理请求
如果不允许不带“主机”标头字段的请求,则可以定义仅丢弃请求的服务器:
server {
listen 80;
server_name "";
return 444;
}
在这里,服务器名称设置为空字符串,该字符串将匹配没有“Host”头字段的请求,并且返回特殊的Nginx
的非标准代码444,以关闭连接。自从版本0.8.48开始,这是服务器名称的默认设置,因此server_name
可以省略。
基于名称和基于IP的混合虚拟服务器
下面来看一个更为复杂的配置,其中一些虚拟服务器侦听不同的地址:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
}
在上面配置中,Nginx
首先根据server
块的listen
指令检测请求的IP地址和端口。然后,它根据与IP地址和端口匹配的server
块的server_name
指令检测请求的“Host”标头字段。如果找不到服务器名称,则默认服务器将处理该请求。例如,192.168.1.1:80
端口上接收到的请求将由192.168.1.1:80
端口的默认服务器(即第一台服务器)处理。
一个简单的PHP站点配置
现在让我们看一下Nginx
处理一个典型的、简单的PHP站点的请求,如下:
server {
listen 80;
server_name example.org www.example.org;
root /data/www;
location / {
index index.html index.php;
}
location ~* \.(png|jpg|gif)$ {
expires 30d;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
无论列出的顺序如何,Nginx
都会首先搜索文字字符串所给出的最特定的前缀location
。在上面的配置当中,唯一的前缀location
是“/”,因为它匹配任何请求,所以它将被用作最后的手段。然后Nginx按照配置文件中列出的顺序检查正则表达式给出的location
。第一个匹配的表达式将停止搜索,Nginx
将使用这个location
。如果没有正则表达式的匹配请求,则Nginx
使用前面找到的最特定的前缀的location
。
注意,所有类型的location
只检测请求的Uri部分,没有参数。这样做是因为查询字符串中的参数可能以几种方式给出,如下:
/index.php?user=john&page=1
/index.php?page=1&user=john
此外,任何人都可以在查询字符串中请求任何东西:
/index.php?page=1&something+else&user=john
现在让我们看一下上面配置中如何处理请求:
- 请求
logo.gif
首先与前缀location
“/”匹配,然后与正则表达式\.(png|jpg|gif)$
匹配,因此,请求由后一个location
匹配。使用伪指令root /data/www
将请求映射到文件/data/www/logo.gif
,然后将文件发送到客户端 - 请求
index.php
也首先与前缀location
“/”匹配,然后与正则表达式\.php$
匹配。因此,请求由后一个location
匹配,并且请求被传递到了localhost:9000
上侦听的FastCGI
服务器上。fastcgi_param
指令将FastCGI
参数SCRIPT_FILENAME
设置为/data/www/index.php
,作为FastCGI
的服务器执行文件。变量document_root
等同于root
指令的值,变量fastcgi_script_name
等同于请求的Uri,即index.php
. - 请求
about.html
仅与前缀location
“/”匹配,因此在该location
进行处理。使用伪指令root /data/www
将请求映射到文件/data/www/about.html
,然后将文件发送到客户端 - 处理请求
/
更为复杂,它仅与前缀location
“/”匹配,因此由该location
处理。然后index
指令根据其参数root /data/www
指令检测文件的存在。如果文件/data/www/index.html
不存在,但是文件/data/www/index.php
存在,则该指令内部将重定向到index.php
,并且Nginx
将再次搜索location
,就好像请求是由客户端发送的一样。如前所述,重定向的请求最终将由FastCGI
服务器处理
在上面栗子当中,我们看到请求FastCGI
服务器时,需要使用fastcgi_pass
替代proxy_pass
,其中uwsgi
、SCGI
、memcached
或gRPC
服务也分别使用uwsgi_pass
、scgi_pass
、memcached_pass
和grpc_pass
指令替代proxy_pass
!