重要提示:在生产环境中使用任何配置前,务必先在测试环境充分验证,确保逻辑正确、性能达标且无安全隐患。配置不当可能导致服务异常、安全漏洞甚至生产事故。
背景:存储告急,如何在线扩容?
随着业务的快速增长,我们的文件存储服务器 /home/data/files2 目录所在的磁盘使用率已飙升至 95%,触发了严重的容量预警,扩容刻不容缓。
但我们面临一个核心挑战:每个文件都已通过固定的 URL(如 http://a.域名.com/files2/a.txt)对外提供服务。直接迁移文件会破坏现有链接,这显然是不可行的。
核心需求清单:
- ✅ 新增一块4TB硬盘,挂载至新目录如
/data2/app/files2。
- ✅ 将部分历史文件迁移到新盘,缓解旧盘压力。
- ✅ 原有访问URL必须保持不变。
- ✅ 客户端访问无任何波动或感知。
- ✅ 未迁移的文件仍能正常访问。
- ✅ 方案需支持未来的持续横向扩展。
- ✅ 最关键:不重启服务、不修改业务代码、实现不停机迁移。
方案:基于 Nginx 命名 Location 的智能路由
我们采用了 主备式多路径存储架构,核心是利用 Nginx 的 try_files 指令搭配 命名 location 功能。其逻辑可以精炼为:“请求优先在旧盘查找,若找不到,则自动跳转到新盘查找,整个过程对用户完全透明。”
这里用到了 Nginx 的一个特性:命名 Location。它的定义方式是在 location 指令后使用 @ 前缀,例如 location @name { … }。
根据 Nginx 官方文档解释:
The “@” prefix defines a named location. Such a location is not used for a regular request processing, but instead used for request redirection. They cannot be nested, and cannot contain nested locations.
简单翻译就是:“@”前缀定义了一个命名位置。这样的位置不用于常规请求处理,而是专门用于请求重定向。它们不能被嵌套,也不能包含嵌套的 location 块。这正符合我们做内部路由跳转的需求。
目标架构与处理流程图
整个文件的查找逻辑遵循以下链式流程,清晰展示了请求是如何在主存储和多个备用存储间流动的:

实战配置详解
场景一:新增单块硬盘
假设我们已将新硬盘挂载到 /data2/app/files2。以下是具体的 Nginx 配置:
server {
listen 80;
server_name a.域名.com;
# 主存储位置(旧硬盘)
location ~* ^/files2/ {
alias /home/data/files2/;
# 优先在当前alias路径查找$uri,找不到则跳转到命名location @newfile_storage
try_files $uri @newfile_storage;
}
# 备用存储位置(新硬盘)- 这是一个命名location,外部无法直接访问
location @newfile_storage {
alias /data2/app/files2/;
# 在新存储路径查找,如果还找不到,则返回404
try_files $uri =404;
}
}
场景二:新增多块硬盘(支持未来持续扩展)
当存储节点进一步增加时,此方案可以轻松扩展,形成多级查找链。以下配置展示了三级存储的查找逻辑:
location ~* ^/files2/ {
root /home/data;
try_files $uri $uri/ @filestorage1;
}
# 第一级备用存储
location @filestorage1 {
alias /data2/app/files2/1/;
try_files $uri $uri/ @filestorage2;
}
# 第二级备用存储
location @filestorage2 {
alias /data2/app/files2/2/;
try_files $uri $uri/ @filestorage3;
}
# 第三级备用存储(链式查找的终点)
location @filestorage3 {
alias /data3/app/files3/;
try_files $uri $uri/ =404;
}
配置解析与操作步骤
1. 主入口 Location 解析
location ~* ^/files2/ {
alias /home/data/files2/;
try_files $uri @newfile_storage;
}
~* ^/files2/:使用不区分大小写的正则匹配,捕获所有以 /files2/ 开头的请求路径。
alias:将请求的URI映射到本地文件系统的 /home/data/files2/ 目录。
try_files $uri @newfile_storage:尝试在 alias 指向的路径查找文件($uri)。如果文件不存在,则内部重定向到名为 @newfile_storage 的 location 继续处理。
2. 命名 Location(新存储)解析
location @newfile_storage {
alias /data2/app/files2/;
try_files $uri =404;
}
@newfile_storage:这是一个内部标记,外部无法通过URL直接访问,仅用于 try_files 重定向。
try_files $uri =404:在新存储路径下查找文件,如果依然找不到,则最终返回 HTTP 404 状态码。
3. 应用配置与验证
- 重载 Nginx 配置(无需重启服务):
nginx -s reload
-
迁移文件并验证:
# 1. 迁移一个测试文件到新目录
mv /home/data/files2/2023-01-video.png /data2/app/files2/
# 2. 验证通过原URL是否仍能访问到该文件
curl -I http://a.domain.com/files2/2023-01-video.png
如果配置正确,即使文件物理位置已经改变,上述 curl 命令仍应返回 200 OK 状态码,证明方案生效。
方案优势总结
| 优势 |
具体说明 |
| 零代码改动 |
业务程序仍向原目录写入文件,无需任何适配修改。 |
| URL永久有效 |
业务方持有的所有文件链接地址保持永久不变。 |
| 客户端无感知 |
用户访问体验无缝,完全感受不到后端存储的变更。 |
| 易于横向扩展 |
通过添加更多命名 location,可轻松扩展至多个存储节点。 |
| 安全可控 |
仅在 Nginx 层面做路由,无需对外暴露额外的服务端口或接口。 |
结语
存储扩容不应成为业务发展的瓶颈。通过巧妙运用 Nginx 的 try_files 指令与 命名 location 机制,我们实现了 “程序零修改、链接永不变、迁移无感知、扩展超灵活” 的平滑扩容方案。
这种方法特别适合为那些需要低成本、高可用、且对在线服务连续性要求极高的文件存储或静态资源服务进行横向扩容。掌握 Nginx 的这些高级特性,能让你的系统架构在面对增长压力时更加游刃有余。

希望这篇实战指南能为你解决类似的存储架构问题带来启发。如果你对 Nginx 或其他 后端与架构 话题有更多兴趣,欢迎在 云栈社区 的技术板块与大家交流探讨。