HTTP请求是如何关联Nginx server{}块的?

Nginx是企业内网的对外入口,它常常同时对接许多应用,因此,Nginx上会同时监听多个端口、为多个域名提供服务。然而,匹配多级域名并不简单,Nginx为此准备了字符串精确匹配、前缀通配符、后缀通配符、正则表达式,当它们同时出现时,弄清楚HTTP请求会被哪个server{ }下的指令处理,就成了一件困难的事。

这是因为基于域名规范,请求匹配server{ }配置块时,并不会按照它们在nginx.conf文件中的出现顺序作为选择依据。而且对于不支持Host头部、没有域名的HTTP/1.0请求和无法匹配到合适server{ }的异常请求,我们都要区别对待。

另外,为了加快匹配速度,Nginx将字符串域名、前缀通配符、后缀通配符都放在了哈希表中,该设计充分使用了CPU的批量载入主存功能。如果不了解这些流程,既有可能导致请求没有被正确的server{ }块处理,也有可能降低了原本非常高效地哈希表查询性能。

本文将沿着Nginx处理HTTP请求的流程,介绍一个请求是如何根据listen、server_name等配置关联到server{ }块的。我们将从TCP连接的建立、Nginx从哪些字段取出域名、域名是怎样与server_name匹配的,讲清楚Nginx如何为请求找到处理它的server{ }块。在实际运维中,大部分问题都是由于请求匹配指令错误造成的,搞清楚这一匹配流程,对我们掌握Nginx非常重要。

 

listen指令对server{ }块的第1次关联


为了让一台服务器可以处理访问多个域名的不同请求,我们用“虚拟主机”来定义一种域名的处理方式,在Nginx中这对应着一个server{ }块。因此,HTTP请求到达时,Nginx首先要找到处理它的server{ }配置块

请求关联server{ }块时主要依据listen和server_name这两个指令,其中listen指令发生在TCP连接建立完成时,它对server{ }块进行首次匹配,等到接收HTTP请求头部时,server_name再进行第二次匹配,这样就可以决定请求由哪个server{ }块中的指令处理。我们先来看listen指令是如何匹配请求的。

Nginx启动时创建socket并监听listen指令告知的端口(包括绑定IP地址)。当运行在TCP协议之上的HTTP请求到达服务器时,操作系统首先收到了TCP三次握手请求。我们知道,TCP这种传输层协议是由内核实现的,因此,由内核完成TCP的三次握手后,就会通过“读事件”经由Linux的Epoll通知到Nginx的worker进程以及具体监听的socket。

 

比如,我们在nginx.conf中配置了以下两个server:

server {
    listen 192.168.1.5:80; 
}
server {
    listen 127.0.0.1:80; 
}

如果是本机进程发来的HTTP请求(在Linux中可以用curl或者telnet发起请求),它的IP报文头部目的IP地址就是127.0.0.1,而TCP报文头部的目的端口就是80。这样,Linux内核就找到了相应的socket,进而通过epoll_wait函数唤醒Nginx进程,而Nginx也就找到了对应的listen指令以及其所属的server{ }块。

版本号

头部长度

服务类型

总长度

标识

标志位

分片偏移

TTL生存时间

上层协议

首部校验和

源IP地址

127.0.0.1

源端口号

80

序列号

确认序列号

首部长度

保留位

U

A

P

R

S

F

窗口大小

校验和

紧急指针

           

你可能注意到,有些server{ }块没有listen指令也可以正常的工作。这是因为Nginx认为每个server{}都应该监听TCP端口,当你没有显式的配置listen指令时,Nginx会默认帮你打开80端口。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值