java架构师培训:Nginx是怎样从HTTP请求中取出域名的
Nginx允许多个server{}块监听相同的端口,所以当访问相同端口、不同域名的请求到达时,还需要根据请求中的域名做第2次匹配,以决定最终关联的server{}块。
这里我们先要搞清楚域名是怎么从HTTP请求中取出来的。在HTTP/1.0协议中并没有Host头部,这是因为互联网起步时,HTTP的设计者并没有考虑到域名的数量会远多于服务器。对于HTTP/1.0请求而言,只能从absoluteURL中携带域名。
举个例子,下面这个没有携带Host头部的请求可以取到www.taohui.pub域名:
GEThttp://www.taohui.pub/index.htmlHTTP/1.
互联网业务的推动导致一台服务器必须要处理大量域名,于是HTTP/1.1协议推出了描述访问域名的Host头部。对于不含有Host头部的HTTP/1.1请求,RFC规范要求服务器必须返回400错误码(Nginx也正是这么做的)。当Host头部与上述absoluteURL中的域名同时出现时,将会以后者为准。例如对于下面这个请求,Nginx会取出www.taohui.tech作为匹配域名:
GEThttp://www.taohui.tech/index.htmlHTTP/1.0
Host:www.taohui.pub
另外,对于使用了TLS/SSL协议的HTTPS请求来说,还可以从TLS握手中获取到域名。关于TLS握手及相关插件我会在后续的文章中再详述。
获取到请求的域名后,Nginx就会将其与上一节中listen指令匹配成功的server块进行第2次匹配,其中匹配依据就是server_name指令后的选项。我们暂且不谈server_name指令的匹配语法,先来看server_name匹配完成后的3种可能情况:
1.域名恰好与1个server{}块中的server_name相匹配,选用该server{}中的指令处理与请求;
2.有多个server{}块匹配上了域名,此时按server_name规定的优先级选中一个server{}块即可;
3.所有server{}块都没有匹配上域名,此时必须有一个默认server{}块来处理这个请求。
其中在第3种情况里,Nginx是这么定义默认server{}的:
1.当listen指令后明确的跟着default_server选项时,它所属的server{}就是默认server。
2.如果监听同一个端口的所有server{}都没有通过listen指令显式设置default_server,那么这些server{}配置块中,在nginx.conf配置文件里第1个出现的就是默认server。
注意,你不能把监听相同端口、地址对的两个server{}块同时设为默认server,否则nginx将无法启动,并给出类似下方的错误输出:
nginx:[emerg]aduplicatedefaultserverfor0.0.0.0:80in/usr/local/nginx/conf/nginx.conf:40
这就是请求匹配server{}块的总体流程,下面我们来看server_name与域名的匹配,这也是最复杂的环节。
相关推荐:java架构师学习路线-Spring技术中常用的扩展点(二)
如果你想了解更多关于java架构师的专业知识,可以加入JAVA架构师交流群:1160405674,里面都是同行,有资源分享包括但不限于(分布式架构、高可扩展、高性能、高并 发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、Mysql 、Zookeeper、Tomcat、Docker、Dubbo、Nginx)。欢迎一到五年的工程师加入,合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
本文地址:https://blog.csdn.net/T_LJAVA/article/details/112595820
上一篇: 使用Guava构建本地缓存