一台服务器跑多个网站?Nginx 反向代理入门
一台云服务器上跑了两个应用,一个在 3000 端口,一个在 8000 端口,浏览器却只能记住域名、默认走 80 端口。直接把端口号写进网址能访问,但难记、难看,换端口还要通知所有人。解决办法是在前面放一个 Nginx:它守着 80 端口,收到请求后按规则转发给后面的应用,浏览器永远只跟 Nginx 打交道。
先分清:正向代理和反向代理不是一回事
正向代理是替浏览器出门,浏览器主动配置它去访问外网;反向代理是替服务器接客,浏览器根本不知道后面有几个应用,也不知道它们在哪个端口。反向代理的好处有三点:端口统一收敛到 80,对外只暴露 Nginx 一个入口;后面加应用、换端口、挪机器,改 Nginx 配置就行,网址不用变;还可以在这一层统一做缓存、限流和 HTTPS,后端应用不用每个都重复做。
第一步:确认 Nginx 在跑,请求真的到了它手里
装好 Nginx 后先确认它在监听 80 端口,并且默认页面能打开:
systemctl status nginx --no-pager
curl -I http://localhost
默认页面能打开,说明 80 端口已经是 Nginx 的了。如果这一步就打不开,先别写配置:看 Nginx 是不是没起来、80 端口是不是被别的程序占了——配置写得再对,请求到不了 Nginx 也没用。
第二步:写一个最小的反向代理配置
假设博客跑在 3000 端口,后台接口跑在 8000 端口。给博客写一个 server 块,放在 Nginx 的配置目录里(常见路径是 /etc/nginx/conf.d/blog.conf):
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
proxy_pass 是核心:请求到了这个 server 块,就原样转发给 3000 端口的应用。后面四行 proxy_set_header 同样重要,不写它们,后端应用看到的 Host 是 127.0.0.1:3000、拿到的访客 IP 也是本机地址,日志里所有访客都会变成同一个 IP,应用里按域名、按 IP 做的逻辑全会错。写配置时容易漏的就是这几行。
第三步:一个域名不够,就按域名和路径分流
一台服务器跑多个应用,靠 server_name 区分。接口服务再加一个 server 块:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
两个域名都解析到同一台服务器,Nginx 按请求里的 Host 头决定进哪个 server 块,博客和接口互不干扰。只有一个域名时,也可以用路径分流:location /api/ 转给 8000 端口,其余转给 3000 端口。路径分流有个坑要注意:location /api/ 后面的 proxy_pass 如果带了 URI,转发时路径会被替换;不带 URI,原始路径原样转发。写之前先想清楚后端应用期望收到的是 /api/users 还是 /users,配错了会出现接口 404,但 Nginx 日志里看着一切正常。
第四步:改完配置,先检查语法再 reload
每次改完配置,不要直接重启 Nginx,先做两步:
nginx -t
systemctl reload nginx
nginx -t 只检查语法和配置能不能加载,不动正在跑的服务;通过了再 reload,让 Nginx 平滑重载新配置,已建立的连接不受影响。直接 restart 也能生效,但会短暂断开所有连接,能 reload 就别 restart。改完后用 curl 带 Host 头验证分流是不是如预期:
curl -I -H "Host: blog.example.com" http://localhost/
curl -I -H "Host: api.example.com" http://localhost/
出问题时,先分清是哪一层
请求打不通时,按顺序定位,不要上来就改配置。先看 Nginx 的错误日志(常见路径 /var/log/nginx/error.log):里面写着 connect() failed,说明 Nginx 没连上后端应用,问题在后端——应用是不是没起来、端口是不是写错了;里面写着 404,说明连上了但路径不对,问题在 location 和 proxy_pass 的写法;日志里什么都没有、浏览器直接连不上,问题在更前面——域名解析、安全组 80 端口放行、Nginx 有没有起来。分清层次再动手,改配置才不会越改越乱。
一个容易忽略的收尾
反向代理接管 80 端口后,后端应用的 3000、8000 端口就没必要再对外暴露了。让它们只监听 127.0.0.1,对外只留 Nginx 的 80 端口(以后上 HTTPS 再加 443),入口收敛到一处,排障和加固都简单得多。入口越多,半夜要查的地方就越多。
一句话收尾
反向代理就做一件事:Nginx 守着 80 端口,按域名或路径把请求交给后面的应用,并把真实的 Host 和访客 IP 原样带过去。配好 server 块、带上四个 proxy_set_header、nginx -t 过了再 reload,一台服务器跑多个网站就顺了。
- 点赞
- 收藏
- 关注作者
评论(0)