nginx根据域名转发,本质就是借助虚拟主机(server块)的server_name匹配规则,将不同域名的请求分发到对应的后端服务或目录,不需要改业务代码,改完配置reload即可生效。
nginx如何根据域名转发:核心配置逻辑拆解
搞懂nginx如何根据域名转发,首先要理解它的请求处理顺序,行业共识认为,nginx处理一个HTTP请求时,会经过一个固定的决策流程:先解析出请求头里的Host字段(也就是用户访问的域名),然后拿这个域名去和所有server块里的server_name做匹配,命中哪个server块,就按这个块里的规则继续处理,整个流程不涉及if判断,不涉及复杂逻辑,纯粹是字符串匹配加上生效优先级。
server_name匹配顺序:转发结果由谁决定
很多人配置nginx多域名时会遇到“明明写了两个server块,为什么所有域名都走了第一个”的情况,这是因为nginx的server_name匹配有一套优先级顺序,按先后排列是:
- 精确匹配(写死的域名,如example.com)
- 通配符前置匹配(如.example.com)
- 通配符后置匹配(如www.example.)
- 正则表达式匹配(如~^(www.)?example.com$)
- 默认server块(listen指令后加上default_server标识)
如果所有server块都没有使用default_server,那么第一个被加载的server块就是默认生效的,这解释了上述现象:第二个server块没被匹配到,是因为第一个server块成了兜底方案,很多人配置多域名时习惯把第一个server块当成“入口”,但实际上没有特殊需求的话,应该把没有server_name或者需要兜底的配置放在第一个,或者明确指定default_server。
具体配置示例:
server {
listen 80 default_server;
server_name _;
return 444;
}
server {
listen 80;
server_name blog.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 80;
server_name shop.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
这个结构下,blog和shop两个域名各自转发到不同的本地端口,访问其他所有域名都会被default_server直接断开连接,这种写法是nginx多域名配置里最基础也最实用的模板。
一个正向代理域名转发场景的配置示例
假设你有一个后台管理域名和一个用户端域名,希望它们指向同一台服务器的不同服务,上面的写法稍加扩展就能满足,关键点在于proxy_pass写的是http://协议加IP加端口,不带URI路径,这样nginx会保留原始请求的URI直接传给后端,如果proxy_pass后面带了路径,比如http://127.0.0.1:8080/,那么原始URI会被替换掉,这是很多nginx根据域名转发后路径丢失的常见原因。

nginx多域名配置:按场景拆解转发需求
nginx多域名配置的难点不在server_name本身,而在于需要转发的目标服务类型和协议各不相同,下面按常见场景拆解。
不同域名转发到不同端口
这是最常见的需求一台服务器上跑了多个服务,比如一个Java应用占8080端口,一个Node.js占3000端口,用nginx按域名分流,核心就是每个server块里各自定义一份location配置,转发目标不同,其他配置互不干扰。
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name app.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的作用是让后端服务拿到真实的Host和用户IP,不然后端看到的请求来源全是127.0.0.1,这在很多业务场景下会导致日志分析失真或者权限校验失败。
域名转发到不同目录(同站点分站)
另一种常见场景是,多个域名共用一个Web服务,但要访问不同的静态目录,比如a.com访问/data/site_a,b.com访问/data/site_b。
server {
listen 80;
server_name a.example.com;
root /data/site_a;
index index.html;
}
server {
listen 80;
server_name b.example.com;
root /data/site_b;
index index.html;
}
这种写法比用location加if判断更干净,也更容易维护,nginx社区对if指令的一般共识是“if is evil”,尤其是在location块里用if做转发判断,容易出现难以排查的坑,按域名拆分成独立的server块,配置职责清晰,修改互不影响。
HTTP域名转发到HTTPS的统一收口
很多站点只启用HTTPS,但用户访问时输入了HTTP域名,这时需要把HTTP流量导到HTTPS,实现方式有两种:
- 每个HTTP server块里写rewrite或者return 301
- 直接监听80端口,所有域名统一跳转
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
这段配置将匹配到的所有HTTP请求统一转为HTTPS,$host保留原始域名,$request_uri保留完整路径,实现无感知跳转,nginx根据域名转发到安全通道的场景里,这种写法是运维人员公认的简洁方案。

nginx域名转发配置失败的排查路径
配置写完不生效,或者生效结果不对,这类问题在nginx域名转发场景里高频出现,排除业务逻辑问题后,按以下顺序排查能省去大量时间。
检查配置文件语法与重载状态
nginx配置修改后不会自动生效,必须手动验证并reload,验证命令是nginx -t,它会对配置做语法检查并输出检测结果,只有显示syntax is ok和test is successful时,reload才有意义。
nginx -t nginx -s reload
很多人在编辑器里改完配置就以为生效了,却忽略了这类基础操作,据统计,相当一部分nginx域名转发配置“无效”的求助帖,实际原因是配置根本没被加载。
检查listen端口和防火墙策略
配置正确、nginx也reload了,但域名还是打不开,这时要看端口能不能通,server块里listen 80,但服务器安全组只放行了443,那HTTP请求自然进不来,用curl命令在本机测试能区分是nginx的问题还是网络层的问题。
curl -H "Host: blog.example.com" http://127.0.0.1/
这个命令模拟了浏览器访问blog.example.com时发出的请求,如果本条命令正常返回了目标服务的响应,说明nginx按域名转发的逻辑是正确的,问题出在域名解析或者云服务商的安全组配置上。
检查server_name写法与DNS解析结果
server_name的匹配是全文匹配而非包含匹配,配置里写了server_name blog.example.com,但用户访问的是blog.example.com.cn或者test.blog.example.com,这都不会命中,另一个容易忽略的点是,如果域名本身还没完成ICP备案,或者DNS解析记录刚改完还没全球生效,即使nginx配置完美也无法访问,用nslookup或者dig命令确认解析结果是排查这类问题的第一步。
nginx反向代理域名转发的性能调优要点
当nginx根据域名转发被用于生产环境时,性能问题不容忽视,转发本身消耗极低,但反向代理场景下的连接管理、缓冲区设置和超时参数会直接影响用户体验。
开启upstream长连接池
默认情况下,nginx和后端服务之间的连接是短连接,每个请求都要重新建连,如果nginx转发到的是本地的高并发服务,TCP握手和挥手的时间损耗会占据请求总耗时的较大比例,在upstream块中开启keepalive能显著改善这一情况。

upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
这里配置了连接池保持32个空闲长连接,同时将HTTP协议版本指定为1.1并清空Connection头,nginx才能复用这些连接,业内专家指出,这种配置对高并发API网关场景的改善效果比较明显,且改动成本很低。
合理设置proxy_buffer与超时
nginx转发时默认会先把后端响应缓冲到内存里再发给客户端,这种设计保护了后端服务不被慢客户端拖累,但如果后端返回的内容很大,buffer太小会导致nginx频繁写临时文件,增加磁盘IO开销,适当调大buffer参数是值得做的优化。
proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; proxy_read_timeout 60s; proxy_connect_timeout 5s;
超时方面,connect_timeout不要设得太大,5秒已经足够覆盖绝大多数局域网内的后端连接场景,read_timeout要根据业务接口的实际耗时来定,接口本身就慢的话,把这个值设得太小会导致用户看到502错误。
nginx根据域名转发用什么配置:常见问题索引
nginx如何根据域名转发到不同端口?
在/etc/nginx/conf.d/目录下新建独立的.conf文件,每个文件定义一个server块,server_name写成目标域名,location块里用proxy_pass指定目标端口,配置完成后执行nginx -t校验并nginx -s reload生效,注意不同域名不要出现在同一个server块里,不然后端无法区分请求归属。
nginx server_name多个域名能写在一起吗?
可以,server_name后面用空格分隔多个域名即可,但这意味着这些域名会共享同一套转发规则,如果想让不同域名转发到不同后端,必须拆分成独立的server块。
nginx域名转发后页面样式丢失是为什么?
页面加载的CSS和JS路径是绝对路径,且写死了原域名,浏览器加载页面后,向原域名发起资源请求,但原域名并没有对应的资源服务,自然就404了,解决方案是让后端服务改为使用相对路径,或者在nginx转发时通过sub_filter模块修改响应内容里的域名,对于前后端分离的项目,更推荐把静态资源和API拆到不同域名下独立配置,而不是在转发层面硬改响应数据。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/746865.html

