Nginx 虚拟主机
Nginx 的虚拟主机既可以支持“基于域名的”,又可以支持“基于 IP 的”。
备注:2012-02-16更新本BLOG,有时我们还需要基于URL前缀(不是域名)的虚拟主机。比如: 我们集团公司 www.example.com很大,有很多子公司,比如有做上海的子公司,于是这个子公司域名是 shanghai.example.com,这个子公司又有很多应用,比如blog和mail,我们可以 blog.shanghai.example.com ,但你也可以不用这么长的子域名,我想用:shanghai.example.com/blog 则是blog应用首页,shanghai.example.com/mail 则是mail应用首页。类似这种我们给它一个名字叫:基于URL前缀虚拟主机(virtual host based on url prefix)
基于域名的虚拟主机很好理解,大家平时见得也很多,简单来讲它是基于 HTTP 请求的可选头 HOST 来分发到不同虚拟主机的。
基于 IP 的虚拟主机,如果一个机器上有两个网卡,分别拥有一个 IP ,让 nginx 分别监听两个网卡上的 80 端口,客户端用不同 IP 访问不同网卡。但是,如果机器上只有一个网卡,依然可以使用基于 IP 的虚拟主机,原因是:一个网卡其实可以配置多个 IP 地址的(这种技术叫做“ IP 别名”)。附录有如何配置 IP 别名的说明。
下面做个简单的实验来同时演示这两种虚拟主机技术:
Nginx 目录结构:
Nginx->html->vh191->aaa->index.html ,内容: vh191’s aaa index ;
Nginx->html->vh191->bbb->index.html ,内容: vh191’s bbb index ;
Nginx->html->vh192->aaa->index.html ,内容: vh192’s aaa index ;
Nginx->html->vh192->bbb->index.html ,内容: vh192’s bbb index 。
网络配置:同一块网卡上,配置了两个 IP ( eth0 和 eth0:1 )。
[root@localhost conf]# /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:A7:39:A2
inet addr:10.228.132.191 Bcast:10.228.133.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:24793 errors:0 dropped:0 overruns:0 frame:0
TX packets:396 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:2783202 (2.6 Mb) TX bytes:25007 (24.4 Kb)
Interrupt:10 Base address:0x2024
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:A7:39:A2
inet addr:10.228.132.192 Bcast:10.255.255.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:24793 errors:0 dropped:0 overruns:0 frame:0
TX packets:396 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:2783202 (2.6 Mb) TX bytes:25007 (24.4 Kb)
Interrupt:10 Base address:0x2024
Nginx 配置文件:
在 http {} 里面配置有 4 个 server 块,分别表示 4 个虚拟主机
server {
listen 10.228.132.191:80;
server_name www.aaa.com;
location / {
root html/vh191/aaa/;
index index.html index.htm;
}
}
server {
listen 10.228.132.191:80;
server_name www.bbb.com;
location / {
root html/vh191/bbb/;
index index.html index.htm;
}
}
server {
listen 10.228.132.192:80;
server_name www.aaa.com;
location / {
root html/vh192/aaa/;
index index.html index.htm;
}
}
server {
listen 10.228.132.192:80;
server_name www.bbb.com;
location / {
root html/vh192/bbb/;
index index.html index.htm;
}
}
配置文件简单解释下, 4 个虚拟主机,各有两个位于 191 上,两个位于 192 上,然后 191 和 192 上又分别用域名 aaa 和 bbb 再生出两个虚拟主机。
查看端口监听情况:
[root@localhost conf]# netstat -ntpl | grep 80
tcp 0 0 10.228.132.192:80 0.0.0.0:* LISTEN 11887/nginx
tcp 0 0 10.228.132.191:80 0.0.0.0:* LISTEN 11887/nginx
[root@localhost conf]#
端口监听情况是 10.228.132.192:80 和 10.228.132.191:80 ,说明两个 IP 都生效了,而且的确是监听在不同的 IP 上。
测试结果:
[root@localhost tenebaul]# curl http://www.aaa.com --proxy 10.228.132.191:80
vh191's aaa index
[root@localhost tenebaul]# curl http://www.bbb.com --proxy 10.228.132.191:80
vh191's bbb index
[root@localhost tenebaul]# curl http://www.aaa.com --proxy 10.228.132.192:80
vh192's aaa index
[root@localhost tenebaul]# curl http://www.bbb.com --proxy 10.228.132.192:80
vh192's bbb index
[root@localhost tenebaul]#
测试结果可以看出, 4 个虚拟主机都生效了。
对应的 access.log 日志:
10.228.132.191 - - [08/Aug/2011:16:27:43 +0800] "GET http://www.aaa.com HTTP/1.1" 200 18 "-" "curl/7.9.8 (i386-redhat-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.7a) (ipv6 enabled)"
10.228.132.191 - - [08/Aug/2011:16:28:08 +0800] "GET http://www.bbb.com HTTP/1.1" 200 18 "-" "curl/7.9.8 (i386-redhat-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.7a) (ipv6 enabled)"
10.228.132.192 - - [08/Aug/2011:16:28:35 +0800] "GET http://www.aaa.com HTTP/1.1" 200 18 "-" "curl/7.9.8 (i386-redhat-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.7a) (ipv6 enabled)"
10.228.132.192 - - [08/Aug/2011:16:29:13 +0800] "GET http://www.bbb.com HTTP/1.1" 200 18 "-" "curl/7.9.8 (i386-redhat-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.7a) (ipv6 enabled)"
第三种虚拟主机:基于URL前缀的虚拟主机(Virtual host based on url prefix)
附录: URL重写请参考 http://eyesmore.iteye.com/blog/1142162
server
{
listen 80;
server_name shanghai.example.com XXX.XXX.XXX.XXXX;
index index.html index.shtml index.htm index.jsp;
root /opt/www/shanghai/WebRoot/;
#limit_conn crawler 20;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#Rewrite Log on, rewrite log will be written into error-log file (info level)
#rewrite_log on;
#static resources in blog subsys
location /blog {
root /opt/www/blog/WebRoot/;
rewrite ^/blog/?$ /index.html break;
rewrite ^/blog/?(.*)$ /$1 break;
access_log off;
}
#dynamic actions(jsp) in blog subsys
location /blog/dynamic/ {
proxy_pass http://blogBackends;
access_log /var/logs/blog_access.log combined buffer=32k;
}
#main system on shanghai.example.com
location / {
proxy_pass http://mainBackends;
access_log /opt/logs/nginx_access.log combined buffer=32k;
}
location ~ .*(WEB-INF)+.*$ {
return 404;
break;
}
location ~* \.(png|jpg|jpeg|gif|ico|swf)$ {
expires 7d;
log_not_found off;
access_log off;
}
location ~* \.(js|css)$ {
expires 3d;
log_not_found off;
access_log off;
}
location ~ .*(\.svn)+.*$ {
return 404;
break;
access_log off;
}
附录一、查看网络配置
一般一个机器的网络配置,我们最关心的是: 1 、本机 IP 地址(含子网掩码); 2 、默认网关; 3 、 DNS 服务器。这三项我们在 windows 下都很熟悉了,那么 linux 的如何查看它们?
1 、 IP 地址和掩码
[tenebaul@localhost tenebaul]$ /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:A7:39:A2
inet addr:10.228.132.191 Bcast:10.228.133.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1252 errors:0 dropped:0 overruns:0 frame:0
TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:100767 (98.4 Kb) TX bytes:2355 (2.2 Kb)
Interrupt:10 Base address:0x2024
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1609 errors:0 dropped:0 overruns:0 frame:0
TX packets:1609 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:109702 (107.1 Kb) TX bytes:109702 (107.1 Kb)
2 、默认网关
[tenebaul@localhost tenebaul]$ /sbin/route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.228.132.0 * 255.255.254.0 U 0 0 0 eth0
169.254.0.0 * 255.255.0.0 U 0 0 0 eth0
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default 10.228.133.254 0.0.0.0 UG 0 0 0 eth0
[tenebaul@localhost tenebaul]$
3 、 DNS 服务器
[tenebaul@localhost tenebaul]$ cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search xxx.corp
nameserver 10.228.128.10
nameserver 10.228.128.13
[tenebaul@localhost tenebaul]$
附录二、配置 IP 别名
1 、增加 IP 别名
用 root 权限执行:
ifconfig eth0:1 10.228.132.192 netmask 255.255.254.0
注意: ifconfig 后面的网卡名字是“ eth0:1 ”,不是“ eth0 ”。如果使用“ eth0 ”,则会覆盖原来的 IP ,使用“ eth0:1 ”的意思是,在“ eth0 ”上配置 IP 别名。
成功执行后,用 ifconfig 查看,你会发现 eth0 和 eth0:1 。
[root@localhost tenebaul]# /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:A7:39:A2
inet addr:10.228.132.191 Bcast:10.228.133.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4251 errors:0 dropped:0 overruns:0 frame:0
TX packets:54 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:369044 (360.3 Kb) TX bytes:4167 (4.0 Kb)
Interrupt:10 Base address:0x2024
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:A7:39:A2
inet addr:10.228.132.192 Bcast:10.255.255.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4251 errors:0 dropped:0 overruns:0 frame:0
TX packets:54 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:369044 (360.3 Kb) TX bytes:4167 (4.0 Kb)
Interrupt:10 Base address:0x2024
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:8064 errors:0 dropped:0 overruns:0 frame:0
TX packets:8064 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:552801 (539.8 Kb) TX bytes:552801 (539.8 Kb)
[root@localhost tenebaul]#
2 、取消 IP 别名
如果需要取消刚才的 eth0:1 的配置,则执行: /sbin/ifconfig eth0:1 down
接着用 ifconfig 查看,就看不到 eth0:1 了。
值得提醒的是:刚才的配置,如果重启服务器,配置则会丢失。此处仅仅是简单实验,没把命令放入 /etc/rc.local 文件中,操作系统启动时加载。