心蓝的博客 心蓝的博客
首页
  • 零基础

    • python零基础入门
  • 专项

    • 正则表达式
  • web框架

    • django框架
    • drf
技术
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档

心蓝

人生苦短,我用python
首页
  • 零基础

    • python零基础入门
  • 专项

    • 正则表达式
  • web框架

    • django框架
    • drf
技术
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • pycharm激活码
  • docker基础
  • Dockerfile
  • docker-compose
  • nginx介绍
  • nginx初学者指南
  • nginx如何处理一个请求
    • 基于命名的虚拟服务器
    • 如何防止处理未定义服务器名的请求
    • 基于名称和ip的混合虚拟服务器
    • 一个简单的PHP站点配置
  • nginx服务名称详解
  • 使用nginx作为http负载均衡器
  • 配置HTTPS服务器
  • 技术
心蓝
2022-06-04
目录

nginx如何处理一个请求

# nginx如何处理一个请求

# 基于命名的虚拟服务器

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;
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在这个配置中,nginx只测试请求的报头字段“Host”,以确定请求应该路由到哪个服务器。如果它的值不匹配任何服务器名,或者请求根本不包含这个报头字段,那么nginx将把请求路由到这个端口的默认服务器。在上面的配置中,默认的服务器是第一个——这是nginx的标准默认行为。它也可以通过listen指令中的default_server参数显式设置哪个服务器应该是默认的:

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}
1
2
3
4
5

default_server参数从0.8.21版本开始就可用了。在早期版本中,应该使用default参数。

请注意,默认服务器是侦听端口的属性,而不是服务器名的属性。稍后再详细介绍。

# 如何防止处理未定义服务器名的请求

如果没有“Host”报头字段的请求不被允许,可以定义一个只删除请求的服务器:

server {
    listen      80;
    server_name "";
    return      444;
}
1
2
3
4
5

在这里,服务器名被设置为一个空字符串,将匹配没有“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;
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在这个配置中,nginx首先根据server块的listen指令来测试请求的IP地址和端口。然后,它根据匹配IP地址和端口的server块的server_name条目测试请求的“Host”报头字段。如果没有找到服务器名,则该请求将由默认服务器处理。

例如,在192.168.1.1:80端口上接收到的www.example.com请求将由192.168.1.1:80端口的默认服务器处理,也就是第一个server,因为没有为这个端口定义www.example.com。

如前所述,默认服务器是监听端口的一个属性,不同的端口可以定义不同的默认服务器:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 一个简单的PHP站点配置

现在让我们来看看nginx是如何为典型的简单PHP站点选择一个位置来处理请求的:

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

    location / {
        index   index.html index.php;
    }

    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Nginx首先搜索由字面值字符串给出的最特定的前缀位置,而不考虑列出的顺序。在上面的配置中,唯一的前缀位置是“/”,因为它匹配任何请求,所以它将被用作最后的手段。然后nginx按照配置文件中列出的顺序检查正则表达式给出的位置。第一个匹配的表达式终止搜索,nginx将使用这个位置。如果没有正则表达式匹配一个请求,那么nginx使用之前找到的最特定的前缀位置。

请注意,所有类型的位置只测试请求行的URI部分,不带参数。这样做是因为查询字符串中的参数可能以几种方式给出,例如:

/index.php?user=john&page=1
/index.php?page=1&user=john
1
2

此外,任何人都可以请求查询字符串中的任何内容:

/index.php?page=1&something+else&user=john
1

现在让我们看看在上面的配置中请求是如何被处理的:

  • 请求“/logo.gif”首先由前缀位置“/”匹配,然后由正则表达式“.(gif|jpg|png)$”匹配,因此,它由后一个位置处理。使用指令" root /data/www ",请求被映射到文件/data/www/logo.gif,然后文件被发送到客户端。
  • 请求" /index.php "也首先由前缀位置" / "匹配,然后由正则表达式" .(php)$ "匹配。因此,它由后一个位置处理,请求被传递到一个FastCGI服务器,这个服务器监听在localhost:9000。fastcgi_param指令将FastCGI参数SCRIPT_FILENAME设置为“/data/www/index.php”,然后FastCGI服务器执行该文件。变量$document_root等于根指令的值,变量$fastcgi_script_name等于请求的URI,即“/index.php”。
  • 请求“/about.html”只与前缀位置“/”匹配,因此,它在这个位置处理。使用指令“root /data/www”,请求被映射到文件/data/www/about.html,文件被发送到客户端。
  • 处理一个“/”的请求更为复杂。它只由前缀位置“/”匹配,因此,它由这个位置处理。然后index指令根据它的参数和“root /data/www”指令测试索引文件是否存在。如果文件/data/www/index.html不存在,并且文件/data/www/index.php存在,那么指令会内部重定向到" /index.php ",然后nginx会再次搜索这个位置,就像这个请求是由客户端发送的一样。正如我们之前看到的,重定向请求最终将由FastCGI服务器处理。

作者:Igor Sysoev

编辑:Brian Mercer

翻译:xinlan

注:本文是对官网文档的翻译

本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。

上次更新: 2023/04/17, 14:40:57
nginx初学者指南
nginx服务名称详解

← nginx初学者指南 nginx服务名称详解→

最近更新
01
requests让接口测试如此简单 原创
03-31
02
最简明的python正则教程
03-30
03
pycharm激活码
12-30
更多文章>
Theme by Vdoing | Copyright © 2019-2025 心蓝
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式