优化 Nginx 配置主域名重定向与 Mongrel 规则迁移
一、主域名重定向
1. 错误示例:在单个 server 块中使用 if
很多从 Apache 迁移过来的用户,习惯通过 if ($http_host…)
在一个 server
中完成所有域名的处理:
server {listen 80;server_name www.example.org example.org;# 这种写法既冗长又不高效if ($http_host = example.org) {rewrite (.*) http://www.example.org$1;}# … 其它配置 …
}
- 问题:Nginx 官方不推荐在
server
级别使用if
去做域名判断,可能引入逻辑漏洞、性能隐患。
2. 推荐做法:独立的重定向 server
最清晰、最高效的实现方式,是为裸域(example.org)和带 www(www.example.org)分别定义两个 server
:
# 1. 裸域重定向到 www
server {listen 80;server_name example.org;return 301 http://www.example.org$request_uri;
}# 2. 带 www 的主站
server {listen 80;server_name www.example.org;# … 主站的其它配置 …
}
- 优点
- 配置简洁:只需一行
return
语句完成 301 永久重定向 - 可读性高:一目了然区分了“重定向域”和“主站域”
- 性能最佳:Nginx 会直接跳过不必要的正则检查
- 配置简洁:只需一行
历史兼容:在 Nginx 0.9.1 之前,不支持
return
,可用:rewrite ^ http://www.example.org$request_uri?;
3. “通配”及默认 server
对于更复杂的场景——如除了 example.com 和 www.example.com 之外的任何请求都统一重定向——可利用默认 server
:
# A. 处理 example.com 和 www.example.com
server {listen 80;server_name example.com www.example.com;# … 主站配置或代理配置 …
}# B. 默认 catch-all,重定向到裸域
server {listen 80 default_server;server_name _;return 301 http://example.com$request_uri;
}
- 说明
default_server
标记此块为默认虚拟主机server_name _;
匹配所有未被显式声明的域名
二、Mongrel 重写规则迁移
原有 Apache + Mongrel 的 .htaccess
里,常见的规则:
DocumentRoot /var/www/myapp.com/current/public# 1. 维护页面优先
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L]# 2. 静态文件优先
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ $1 [QSA,L]RewriteCond %{REQUEST_FILENAME}/index.html -f
RewriteRule ^(.*)$ $1/index.html [QSA,L]RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [QSA,L]# 3. 其余请求代理到 Mongrel 集群
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
1. Nginx 等价配置
在 Nginx 中,可借助 try_files
和命名 location
来简洁表达:
# 定义后端 Mongrel upstream
upstream mongrel {server 127.0.0.1:8000;server 127.0.0.1:8001;# … 根据实际拓扑添加 …
}server {listen 80;server_name myapp.com www.myapp.com;root /var/www/myapp.com/current/public;location / {# 先尝试维护页面try_files /system/maintenance.html# 再尝试静态资源$uri # 原始请求路径$uri/index.html # 请求目录下的 index.html$uri.html # 请求附带 .html# 若以上均不存在,转向 @mongrel@mongrel;}location @mongrel {proxy_pass http://mongrel;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 如有需要,可添加 WebSocket、超时等设置}
}
- 工作流
- 维护页面:如果
/system/maintenance.html
存在,一律返回维护页 - 静态文件:依次判断
$uri
、$uri/index.html
、$uri.html
是否存在 - 动态请求:由
@mongrel
代理到后端集群
- 维护页面:如果
2. 优化与注意
- 缓存与 gzip:可在
location /
之外,针对静态文件添加expires
、gzip_static on
等指令 - 安全与限流:为
@mongrel
或主站添加limit_req
、limit_conn
,防止瞬时洪泛 - 日志分离:根据业务特点,分别对静态和动态请求输出不同日志级别与路径
三、总结
- 域名重定向:务必使用独立的
server
,避免在if
中做域名判断。 - Mongrel 迁移:通过
try_files + 命名 location
,将 Apache 的多条RewriteRule
合并为简洁高效的 Nginx 配置。
掌握以上两类常见场景的最佳实践,能让你的 Nginx 配置既简洁又高效,为生产环境保驾护航。