什么是 Server 块?
在 Nginx 中,Server 块 (也叫做虚拟主机配置)是路由分发的基础单元。Nginx 通过 listen 和 server_name 两个关键参数,决定每个请求该由哪个 Server 块处理,从而实现一台服务器托管多个网站。
可以把 Server 块想象成 Nginx 内部的"虚拟服务器"------每个 Server 块独立配置自己的域名、端口、根目录和路由规则,互不干扰。
一、基础配置:listen + server_name
最基本的 Server 块配置如下:
nginx
server {
listen 80; # 监听端口
server_name localhost; # 域名匹配
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
listen ------ 监听端口
| 写法 | 说明 |
|---|---|
listen 80; |
监听 IPv4 的 80 端口 |
listen [::]:80; |
监听 IPv6 的 80 端口 |
listen 8080; |
监听非标准端口(如 8080) |
listen 443 ssl; |
监听 HTTPS 端口并启用 SSL |
listen 80 default_server; |
设为默认服务器,当没有匹配时使用 |
server_name ------ 域名匹配
server_name 匹配的是请求头中的 Host 字段 。浏览器访问 http://example.com 时,请求头中会携带 Host: example.com,Nginx 拿这个值与所有 Server 块的 server_name 对比,找到对应的处理规则。
可以在浏览器开发者工具 → 网络面板中查看每个请求的
Host请求头。
二、请求路由流程
当一个请求到达 Nginx 时,匹配顺序如下:
arduino
客户端请求 ──→ 根据 listen 端口找到 Server 块列表
│
▼
根据 server_name 匹配 Host 请求头
│
┌──────────┼──────────┐
▼ ▼ ▼
精确匹配 通配符匹配 正则匹配
│
▼
进入对应的 Server 块
│
▼
继续匹配 location 路由
如果所有 server_name 都没有匹配到,Nginx 会使用该端口上第一个 Server 块(或标记了 default_server 的那个)来处理请求。
三、多域名实战
场景
假设我们有一个 Nginx,想同时托管两个网站:
第一步:修改 hosts 文件
由于本机没有真实的域名解析,需要在本机的 hosts 文件中添加域名映射,把两个域名指向本地:
bash
# Windows: C:\Windows\System32\drivers\etc\hosts
# Linux/macOS: /etc/hosts
127.0.0.1 blog.com
127.0.0.1 login.com
修改 hosts 后在 Windows 上需要刷新 DNS 缓存才能生效:
bash
ipconfig /flushdns
这样访问 blog.com 和 login.com 就会解析到本机。
第二步:准备站点目录
arduino
nginx-learning/
├── conf.d/
│ ├── blog.conf # blog.com 配置
│ └── login.conf # login.com 配置
├── html/
│ ├── blog/
│ │ └── index.html # blog 站点首页
│ └── login/
│ └── index.html # login 站点首页
└── docker-compose.yml
第三步:Nginx 配置
blog.conf:
nginx
server {
listen 80;
server_name blog.com;
location / {
root /usr/share/nginx/html/blog;
index index.html index.htm;
}
}
login.conf:
nginx
server {
listen 80;
server_name login.com;
location / {
root /usr/share/nginx/html/login;
index index.html index.htm;
}
}
第四步:重载配置
bash
# 验证配置是否正确
docker exec nginx-learning nginx -t
# 重载配置(不中断服务)
docker exec nginx-learning nginx -s reload
验证效果
bash
curl http://blog.com:8080/ # 返回 blog 站点的页面
curl http://login.com:8080/ # 返回 login 站点的页面
✅ 同一个 Nginx、同一个端口(80),通过不同的域名路由到不同的网站目录,这就是虚拟主机的核心能力。
四、server_name 匹配规则详解
server_name 支持多种匹配方式,灵活应对不同场景:
1. 精确匹配(完全匹配)
nginx
server_name example.com;
server_name www.example.com;
必须与请求的域名完全一致才匹配。
2. 通配符匹配
* 只能出现在开头或结尾,不能放在中间:
nginx
server_name *.example.com; # 匹配 www.example.com、api.example.com 等
server_name mail.*; # 匹配 mail.example.com、mail.test.com 等
server_name *.example.*; # ❌ 错误写法,通配符不能同时出现在开头和结尾
3. 正则匹配(~ 开头)
以 ~ 开头,后面跟正则表达式,提供最灵活的匹配能力:
nginx
server_name ~^www\d+\.example\.com$; # 匹配 www1.example.com、www2.example.com 等
server_name ~^(?<subdomain>.+)\.example\.net$; # 支持捕获变量,可在配置中引用 $subdomain
注意事项:
- 正则表达式必须以
~开头 - 正则中的
.需要转义为\\. - 正则匹配不区分大小写(如果需要区分大小写,使用
~*)
4. 多域名并列
一个 Server 块可以指定多个域名,用空格隔开:
nginx
server_name example.com www.example.com blog.example.com;
5. 特殊值
| 写法 | 说明 |
|---|---|
server_name _; |
下划线是常见的无效域名占位符 ,表示匹配任意未定义的域名,通常配合 default_server 使用 |
server_name ""; |
匹配没有 Host 请求头的请求(如 HTTP/1.0 请求) |
完整的多站点示例
nginx
# 站点 1:主站
server {
listen 80;
server_name example.com www.example.com;
location / {
root /var/www/main;
}
}
# 站点 2:API 子域名
server {
listen 80;
server_name api.example.com;
location / {
root /var/www/api;
}
}
# 站点 3:捕获所有未匹配的域名(兜底)
server {
listen 80 default_server;
server_name _;
return 444; # 直接关闭连接,不给任何响应
}
五、server_name 匹配优先级
当多个 Server 块的 server_name 都能匹配同一个域名时,Nginx 按以下优先级只选一个:
| 优先级 | 匹配方式 | 示例 |
|---|---|---|
| 1(最高) | 精确匹配 | example.com |
| 2 | 通配符开头 | *.example.com |
| 3 | 通配符结尾 | www.* |
| 4(最低) | 正则匹配 | ~^www\\.\\d+\\.com$ |
重要 :正则匹配实际上在通配符之后被检查,且 Nginx 会按配置文件中 正则出现的顺序 逐一尝试,匹配到第一个即停止。因此如果有多个正则都可能匹配,注意先后顺序。
六、default_server 的用法
default_server 用于指定某个 Server 块作为默认处理器,当没有其他规则匹配时使用:
nginx
server {
listen 80 default_server;
server_name _;
location / {
return 404;
}
}
常见用途:
- 拦截未绑定的域名 ------ 返回 404 或 444(直接关闭连接)
- 统一重定向 ------ 将所有未匹配的请求重定向到主站
- 统一 HTTPS 跳转 ------ 将所有 HTTP 请求跳转到 HTTPS
如果没有显式指定
default_server,Nginx 会使用该端口上的第一个 Server 块作为默认。
总结
通过本文,你已经掌握了 Nginx Server 块的核心配置:
| 知识点 | 要点 |
|---|---|
| Server 块 | 虚拟主机的基本单元,每个块独立管理一个站点的路由规则 |
| listen | 指定监听的端口和协议 |
| server_name | 匹配请求头的 Host 字段,决定请求由哪个 Server 块处理 |
| 请求路由流程 | listen 过滤端口 → server_name 匹配域名 → location 匹配路径 |
| 匹配规则 | 精确匹配 > 通配符开头 > 通配符结尾 > 正则匹配 |
| default_server | 未匹配时的兜底方案,用于拦截非法域名或统一重定向 |
| 多域名实战 | 修改 hosts → 编写多个 server 块 → 重载配置即可实现一机多站 |