Skip to content

Latest commit

 

History

History
200 lines (146 loc) · 7.57 KB

05、一个nginx服务器为多个ip服务.md

File metadata and controls

200 lines (146 loc) · 7.57 KB

程序员技术交流、面试、职场、生活、游戏,综合讨论QQ群:387017550,群内经常发红包,欢迎加入

05、一个nginx服务器为多个 IP 服务

1、效果解释

简单来说,访问多个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 时,去访问新服务器;

2、实现方法:

  1. 先判断 192.168.0.151 和 192.168.0.152 是否有机器存在(方法:ping 两个ip);
  2. 添加 IP 别名,让以上2个IP,在访问的时候指向 nginx 所在服务器;
    1. 具体来说,ifconfig 找到网卡名、ip地址,netmask,broadcast;
    2. 输入以下命令(记得替换 [] 内的内容);
    3. /sbin/ifconfig [网卡名]:1 [新的ip] broadcast [原本网卡的broadcast的值] netmask [原netmask值] up
    4. /sbin/route add -host [新的ip] dev [网卡名]:1
    5. 然后ifconfig查看是否添加成功;
    6. 如果添加多个,则网卡名后面的 :1 变为 :2 ,依次类推。也可以 :1 改为 :abc 之类的;
    7. 以上的临时添加方案(重启后失效);
    8. 永久方案是,将以上内容,添加到 /etc/rc.local文件的末尾,然后保存即可;
    9. 如果永久方案无效,可能是没权限的原因,执行:chmod +x /etc/rc.local
    10. 或者参考一下这个链接的方案:https://blog.csdn.net/rj042/article/details/8246966
  3. 在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;
        }
    }
  1. 这代表如果访问 192.168.0.151 ,则会访问 ./html 文件夹,默认是 index.html;
  2. 访问 192.168.0.152 ,则会访问 ./html2 文件夹中的文件,默认是 index.html;

3、测试方案:

  1. 先按以上做;
  2. 将原本 nginx 文件夹下的 html 文件夹,复制一份,改名 html2;
  3. 更改 html2/index.html 的内容,例如删除正文;
  4. 执行 nginx -s reload 重新读取配置文件(因为在上面更新过一次);
  5. 依次访问 192.168.0.151 和 192.168.0.152 查看是否正常;
  6. 建议先尝试非永久性改变,正常后再去改配置文件实现永久性改动;

4、server_name 和 listen 属性的匹配原则

当我们配置多个server属性的时候,他会按一定规则,顺序匹配。

具体来说,他会先匹配端口,以下面两个server配置为例。

server {
    listen       80;
    server_name  192.168.0.151;
    // 其他略
}

server {
    listen       80;
    server_name  192.168.0.152;
    // 其他略
}

假如访问 192.168.0.151192.168.0.152192.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。

总结:

  1. 简单来说,当你访问nginx服务器的时候,他会优先匹配 listen 和 server_name 都符合的;
  2. 如果只有其中一个符合,那么会优先匹配 listen 符合的;
  3. 如果都符合,则优先匹配第一个 server ;
  4. 除此之外,在上面未提到 server_name 除了写死,还可以写成通配符、正则等形式;
  5. 具体参照 https://my.oschina.net/jiangshanlinux/blog/1505935

4、补充说明

4.1、一个虚拟主机监听多个ip?

在上面我们实现的是一个虚拟主机监听一个 IP,但是假如监听多个 IP 如何实现?前提是这些 IP 监听同一个端口。

答案很简单,这么写就行了:

server {
    listen       80;
    server_name  192.168.0.151 192.168.0.152;

也可以利用正则、通配符的方式来写,参考【4、server_name 和 listen 属性的匹配原则】给的链接即可。

4.2、我有10个ip访问同一个主机,但是只有1个ip是单独处理的,其他9个都是访问同样的页面,这9个怎么配置?

我们只需要配 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 无法被正确处理)。