关于Nginx中虚拟主机的一些冷门知识小结


Posted in Servers onMarch 03, 2022

前言

nginx的虚拟主机,不知道大家了解不。以前吧,如果在nginx上要反向代理多个服务,我一般是让nginx监听多个不同端口,比如8080/8081,不同端口,反向代理到不同的服务。

server {
	listen 9981 so_keepalive=on;
	proxy_pass service1;
}

server {
	listen 9982 so_keepalive=on;
	proxy_pass service2;
}

来了现在公司,发现这边是基于域名(端口都是80)来反向代理到不同服务,如下:

关于Nginx中虚拟主机的一些冷门知识小结

关于Nginx中虚拟主机的一些冷门知识小结

基于以上的nginx配置,域名a和b,分别代表了系统a和系统b,实际dns是指向同一台nginx机器。当你用域名a访问时,就会走上面的配置;域名b访问时,就会走下面的配置。

对线上配置的一个小疑问

问题背景

我的一位同事,和我差不多时间入职,接手了一个几年前的系统,看到线上环境的nginx配置,表示有点懵,不知道how it works。

这里把这个问题,简单描述下。

为了方便我这边模拟,假设机器ip为10.0.0.6,机器上有个python脚本,会去访问一个api:http://10.0.0.6:80 。

机器上的/etc/hosts如下:

[root@VM-0-6-centos nginx]# cat /etc/hosts
......

10.0.0.6 bbbb.com

也就是说,访问bbbb.com,就相当于访问这台机器了。

[root@VM-0-6-centos nginx]# ping bbbb.com
PING bbbb.com (10.0.0.6) 56(84) bytes of data.

基于以上信息,这个api访问本机的80,是会到本机的nginx(nginx监听80端口),nginx配置如下:

关于Nginx中虚拟主机的一些冷门知识小结

这个配置,基于我们对虚拟主机的了解,也就是说,访问aaaa.com,就会到第一段的配置,aaaa.access.log里面就会有访问日志;如果是访问bbbb.com,就会到第二段的配置,bbbb.access.log就会有访问日志。

但是,客户端不按套路出牌啊,用的是,10.0.0.6:80/xx这样的url来访问该nginx,同时,/etc/hosts里面有配置bbbb.com指向本机,那么,大家觉得最终的访问结果如何?

实测结果

结果是,访问了aaaa那一段。

关于Nginx中虚拟主机的一些冷门知识小结

这。。。我们就有点想不通了,没理由啊,为啥呢,why?不是不能接受结果,而是不知道为什么会这样。

探索

排查网络

按理说,用域名形式访问,应该才会去查看/etc/hosts文件和dns系统,找到域名背后的ip;但是,按ip访问,貌似java建立里面的socket底层实现利,也会有根据ip去获取host的代码(还导致一些超时问题之类的)。

所以,我们猜测,难道是,访问10.0.0.6时,查看了/etc/hosts,把10.0.0.6转换成了aaaa.com?但是,/etc/hosts里面只有把10.0.0.6转换为bbbb.com的可能性吧?

本着不管三级二十一,先抓个包再说的想法,于是在nginx的80端口,开了个tcpdump:

[root@VM-0-6-centos ~]# tcpdump -i lo tcp port 80 -Ann

然后再次访问:

[root@VM-0-6-centos nginx]# curl 10.0.0.6:80

抓包结果:

关于Nginx中虚拟主机的一些冷门知识小结

看到这边host是 10.0.0.6.

这让我开始怀疑,可能和/etc/hosts没什么关系,问题应该变成了:nginx在拿到上面这段http报文时,为啥要路由到aaaa.com那一段配置里面去。

排查nginx

怎么才能知道nginx做了啥呢,我们又没有代码,但是,好歹,我们还有shell 命令啊。 strace这个命令,可以查看一个进程的系统调用,还是比较好用的。

为啥要查这个?因为我怀疑是不是nginx拿到10.0.0.6后,把它转成了域名,不过,转的话,应该也是转换为bbbb.com。另外,这个命令有没有用,我也不确定,因为该命令只能看这个进程发起了哪些系统调用(不是java里的rpc),而是对内核发起的系统调用(system call)。万一,ip转域名的部分,没有通过系统调用实现的话,那这个命令就失效了。

不过还是试试?

先拿到了nginx的worker进程的pid:8845

[root@VM-0-6-centos nginx]# ps -ef|grep nginx
root       610     1  0 12:15 ?        00:00:00 nginx: master process ./nginx
nobody    8845   610  0 13:13 ?        00:00:00 nginx: worker process

再开启一个strace:

[root@VM-0-6-centos ~]# strace -p 8845 -s 1024 -q -f -v -e  trace=network

结果如下:

关于Nginx中虚拟主机的一些冷门知识小结

好像只有接收网络请求的系统调用(recvfrom),系统调用,大家可以拿这个函数名去网上查。

关于Nginx中虚拟主机的一些冷门知识小结

此时,排查陷入了僵局,于是,我只能提议,我先回座位上找找nginx相关资料。

然后就开始在网上查,运气也还不错,就找到了:

https://docs.nginx.com/nginx/admin-guide/web-server/web-server/

关于Nginx中虚拟主机的一些冷门知识小结

上面这段话,大概就是说,虚拟主机的匹配,是通过取req报文里的host字段,来和nginx.conf中server里的server_name做匹配,

因为server_name可以是通配符之类的,所以这里有个优先级,完全匹配》模糊匹配。

上图的最后那几行,就是关键了:

如果完全没匹配上(我们这里就是,拿了个ip来匹配,然而nginx.conf里配置的是aaaa.com和bbbb.com),就会路由到这个端口的默认server。默认server是哪个呢,就是:nginx.conf里端口为80的、且写在第一个的server。

ok,打完收工。

总结

知识点可能很小,但排查也比较麻烦,因为线上环境不好动,然后配置的域名其实不止两个,有7/8个,中间绕的路比上面其实还多一点。

不过这边的大概思路是这样的,希望对大家也有一点点帮助。

Servers 相关文章推荐
nginx常用命令放入shell脚本详解
Mar 31 Servers
nginx 反向代理之 proxy_pass的实现
Mar 31 Servers
nginx 多个location转发任意请求或访问静态资源文件的实现
Mar 31 Servers
Windows下使用Nginx+Tomcat做负载均衡的完整步骤
Mar 31 Servers
CKAD认证中部署k8s并配置Calico插件
Mar 31 Servers
Tomcat执行startup.bat出现闪退的原因及解决办法
Apr 20 Servers
Win10 Anaconda安装python-pcl
Apr 29 Servers
nginx 配置缓存
May 11 Servers
永中文档在线转换预览基于nginx配置部署方案
Jun 10 Servers
Windows Server 2008配置防火墙策略详解
Jun 28 Servers
nginx访问报403错误的几种情况详解
Jul 23 Servers
SpringBoot前端后端分离之Nginx服务器下载安装过程
Aug 14 Servers
nginx负载功能+nfs服务器功能解析
Apache Pulsar集群搭建部署详细过程
Feb 12 #Servers
详解nginx安装过程并代理下载服务器文件
Feb 12 #Servers
nginx从安装到配置详细说明(安装,安全配置,防盗链,动静分离,配置 HTTPS,性能优化)
Nginx性能优化之Gzip压缩设置详解(最大程度提高页面打开速度)
Feb 12 #Servers
使用 Apache Dubbo 实现远程通信(微服务架构)
Nginx 反向代理解决跨域问题多种情况分析
Jan 18 #Servers
You might like
php反弹shell实现代码
2009/04/22 PHP
老版本PHP转义Json里的特殊字符的函数
2015/06/08 PHP
JavaScript 编程引入命名空间的方法与代码
2007/08/13 Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
2012/01/15 Javascript
jQuery学习笔记(1)--用jQuery实现异步通信(用json传值)具体思路
2013/04/08 Javascript
jquery索引在使用中的一些困惑
2013/10/24 Javascript
js如何判断用户是否是用微信浏览器
2014/06/05 Javascript
JavaScript基础语法、dom操作树及document对象
2014/12/02 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
2014/12/20 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
2015/07/17 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
2016/01/21 Javascript
JS动态生成年份和月份实例代码
2017/02/04 Javascript
webpack3里使用uglifyjs压缩js时打包报错的解决
2018/12/13 Javascript
浅谈js闭包理解
2019/03/28 Javascript
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
[03:40]DOTA2亚洲邀请赛小组赛第二日 赛事回顾
2015/01/31 DOTA
Python编程实现删除VC临时文件及Debug目录的方法
2017/03/22 Python
Python秒算24点实现及原理详解
2019/07/29 Python
详解python中*号的用法
2019/10/21 Python
python关于变量名的基础知识点
2020/03/03 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
英国著名的药妆网站:Escentual
2016/07/29 全球购物
美国在线工具商店:Acme Tools
2018/06/26 全球购物
美国在线眼镜店:GlassesShop
2018/11/15 全球购物
俄罗斯电子产品在线商店:UltraTrade
2020/01/30 全球购物
速卖通欧盟:Aliexpress EU
2020/08/19 全球购物
团员个人的自我评价
2013/12/02 职场文书
教师现实表现材料
2014/02/14 职场文书
《小壁虎借尾巴》教学反思
2014/02/16 职场文书
ktv总经理岗位职责
2014/02/17 职场文书
初中班主任经验交流材料
2014/05/16 职场文书
家长学校培训材料
2014/08/20 职场文书
关于十八大的演讲稿
2014/09/15 职场文书
法人单位适用的授权委托书
2014/09/19 职场文书
装配出错检讨书
2014/09/23 职场文书
公司借条范本
2015/05/25 职场文书