程序员技术交流、面试、职场、生活、游戏,综合讨论QQ群:387017550,群内经常发红包,欢迎加入
简单来说,访问多个ip,都会交由同一个nginx服务器处理,但是显示不同页面内容(即交给不同 server 处理)。
举例来说,通常,访问 192.168.0.151 这个ip会访问 A服务器,访问 192.168.0.152 这个ip会访问 B服务器。
假如你有2个服务,但只有一台机子。
- 在之前,你需要通过 a.com/a 来访问同一个服务器 A 服务;
- 访问 a.com/b 来访问同一个服务器的 B 服务;
- 这样才解耦方便独立管理;
- 缺点是 A、B 两个服务,还是有一定耦合度,也不方便。
但假如你想将这2个拆分出来,像正常使用了2个服务器一样,就可以配置基于 ip 的虚拟主机,并利用 nginx 通过配置 server属性,来让其在访问不同 ip 的时候,访问同一台机子的不同静态文件(这是最基础的用法)。
举例来说,我遇见这样一个场景:
- 我有 A 页面、B 页面;
- 我希望访问 192.168.0.151 时,进入 A 页面,访问 192.168.0.152 时,进入 B 页面;
- 现在 A 页面比较简单,但以后 A 页面可能会复杂起来,可能会使用一个独立的服务器;
- 为了对用户友好(不需要自己改变保存的地址),因此希望用户一直访问同一个ip即可,对于我切换是无感知的;
- 虽然以后 A 会独立出来,但现在A、B分别用一个服务器就太浪费了;
所以我期望是这样的:
- 我现在只使用一个服务器;
- 访问 192.168.0.151 和 192.168.0.152 时,都会访问到这个服务器(多IP对单服务器);
- 访问 192.168.0.151 时,进入 A 页面,访问 192.168.0.152 时,进入 B 页面;
- 以后 A 独立后,直接开一个新服务器,访问 192.168.0.151 时,去访问新服务器;
- 先判断 192.168.0.151 和 192.168.0.152 是否有机器存在(方法:ping 两个ip);
- 添加 IP 别名,让以上2个IP,在访问的时候指向 nginx 所在服务器;
- 具体来说,ifconfig 找到网卡名、ip地址,netmask,broadcast;
- 输入以下命令(记得替换 [] 内的内容);
/sbin/ifconfig [网卡名]:1 [新的ip] broadcast [原本网卡的broadcast的值] netmask [原netmask值] up
/sbin/route add -host [新的ip] dev [网卡名]:1
- 然后ifconfig查看是否添加成功;
- 如果添加多个,则网卡名后面的 :1 变为 :2 ,依次类推。也可以 :1 改为 :abc 之类的;
- 以上的临时添加方案(重启后失效);
- 永久方案是,将以上内容,添加到
/etc/rc.local
文件的末尾,然后保存即可; - 如果永久方案无效,可能是没权限的原因,执行:
chmod +x /etc/rc.local
; - 或者参考一下这个链接的方案:https://blog.csdn.net/rj042/article/details/8246966
- 在nginx的配置文件
nginx/conf/nginx.conf
文件中,原本 server 属性的同级位置添加以下代码:
# 第二个虚拟主机
server {
listen 192.168.0.151:80;
server_name 192.168.0.151 default;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 第三个虚拟主机
server {
listen 192.168.0.152:80;
server_name 192.168.0.152;
location / {
root html2;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- 这代表如果访问 192.168.0.151 ,则会访问
./html
文件夹,默认是 index.html; - 访问 192.168.0.152 ,则会访问
./html2
文件夹中的文件,默认是 index.html;
- 先按以上做;
- 将原本 nginx 文件夹下的 html 文件夹,复制一份,改名 html2;
- 更改 html2/index.html 的内容,例如删除正文;
- 执行
nginx -s reload
重新读取配置文件(因为在上面更新过一次); - 依次访问 192.168.0.151 和 192.168.0.152 查看是否正常;
- 建议先尝试非永久性改变,正常后再去改配置文件实现永久性改动;
当我们配置多个server属性的时候,他会按一定规则,顺序匹配。
具体来说,他会先匹配端口,以下面两个server配置为例。
server {
listen 80;
server_name 192.168.0.151;
// 其他略
}
server {
listen 80;
server_name 192.168.0.152;
// 其他略
}
假如访问 192.168.0.151
, 192.168.0.152
, 192.168.0.153
都可以访问到这个server(默认是80端口)。
访问不同的 IP,如何匹配?
访问 192.168.0.151
先匹配第一个server,listen和server_name都匹配成功,第一个server来处理。
访问 192.168.0.152
他会先去匹配第一个server,首先 listen 匹配成功,但是 server_name 匹配失败。
于是再去匹配第二个,匹配成功,于是通过第二个 server 来处理。
访问 192.168.0.153
由于两个server都没有完全匹配成功,但是端口匹配两个都成功,因此匹配到了第一个端口匹配成功的 server。
总结:
- 简单来说,当你访问nginx服务器的时候,他会优先匹配 listen 和 server_name 都符合的;
- 如果只有其中一个符合,那么会优先匹配 listen 符合的;
- 如果都符合,则优先匹配第一个 server ;
- 除此之外,在上面未提到 server_name 除了写死,还可以写成通配符、正则等形式;
- 具体参照 https://my.oschina.net/jiangshanlinux/blog/1505935
在上面我们实现的是一个虚拟主机监听一个 IP,但是假如监听多个 IP 如何实现?前提是这些 IP 监听同一个端口。
答案很简单,这么写就行了:
server {
listen 80;
server_name 192.168.0.151 192.168.0.152;
也可以利用正则、通配符的方式来写,参考【4、server_name 和 listen 属性的匹配原则】给的链接即可。
我们只需要配 2 个 server 就可以了。
单独处理的 IP ,在server中的 server_name 写单独处理的 IP,listen 写监听的 IP(实现双精准匹配效果);
剩下的,可以使用通配符匹配,或者只做到端口匹配即可(注意不要触发双精准匹配),然后将这个server配置放在前面;
双精准匹配参考上面的【4、server_name 和 listen 属性的匹配原则】。
具体来说,ip地址是 192.168.0.151 ~ 192.168.0.160,需要单独处理的是 192.168.0.151,那么这么写。
server {
listen 80;
server_name 192.168.0.*;
// 其他略
}
server {
listen 80;
server_name 192.168.0.151;
// 其他略
}
或者这么写:
server {
listen 80;
server_name 192.168.0.152;
// 其他略
}
server {
listen 80;
server_name 192.168.0.151;
// 其他略
}
前者可以颠倒先后顺序,后者必须精准匹配的放置在后面(不然其他的 IP 无法被正确处理)。