网址的域名和路径:DNS和Web服务器
网址的域名和路径:DNS和Web服务器
概述
URL(Uniform Resource Locator,统一资源定位符)是互联网上用于定位和访问资源的标准地址。我们日常在浏览器地址栏中输入的网址,其实就是一个 URL,例如:
1 | https://example.com |
URL 属于 URI(Uniform Resource Identifier,统一资源标识符)的一种。URI 是一个更广义的概念,指代用于标识资源的字符串,不一定能直接访问。例如:
1 | /home/sample |
虽然这个路径不能直接访问,但它是一个 URI,因为它标识了服务器上的某个资源。可以这样理解:
所有的 URL 都是 URI,但并非所有 URI 都是 URL。
一个完整的 URL 通常包含以下几个部分:
1 | 协议://主机名[:端口]/路径[?查询参数][#片段标识符] |
以下是一个完整 URL 的示例及其各部分说明:
1 | https://www.example.com:443/home/page.html?lang=en#section2 |
部分 | 示例内容 | 说明 |
---|---|---|
协议(Scheme) | https |
指定使用的协议,如 HTTP、HTTPS、FTP 等 |
主机名(Host) | www.example.com |
服务器的域名 |
端口号(Port) | 443 (可省略) |
通信使用的端口号(HTTPS 默认端口为 443) |
路径(Path) | /home/page.html |
请求的资源在服务器上的位置 |
查询参数(Query) | ?lang=en |
可选,通常用于向资源传递参数 |
片段标识符(Fragment) | #section2 |
可选,用于定位页面内的特定位置,不参与请求 |
在理解 URL 时,最关键的是区分“域名”与“路径”这两个组成部分。我们以如下网页为例:
1 | https://www.ifs.tohoku.ac.jp/komiya/event/2025/index.html |
当浏览器发起请求时,会将 URL 拆解为多个部分,分别用于不同的网络通信阶段。例如,在 HTTP/1.1 中,请求头通常如下:
1 | GET /komiya/event/2025/index.html |
Host
头部字段:告知服务器请求是发送给哪一个域名(主机),这里是www.ifs.tohoku.ac.jp
。- 请求行中的路径部分
/komiya/event/2025/index.html
:指定了在该主机上的资源位置。
而在 HTTP/2 中,传统的请求行被更清晰的“伪首部字段(pseudo-headers)”所取代,请求头看起来像这样:
1 | :method: GET |
字段 | 说明 |
---|---|
:method |
HTTP 方法,如 GET、POST 等 |
:path |
资源路径 |
:scheme |
协议类型(http 或 https) |
:authority |
域名(等价于 HTTP/1.1 的 Host ) |
通过清晰划分域名与路径,接下来的内容将讨论两个关键组件:DNS 和 Web 服务器,它们在处理请求过程中分别作用于 URL 的不同部分。
- DNS(域名系统):负责将域名解析为 IP 地址,处理的是 URL 中的主机名部分。
- Web 服务器:接收到请求后,根据路径部分找到对应资源并返回内容,处理的是 URL 中的路径部分。
DNS 解析:我来查找域名
DNS(Domain Name System,域名系统)负责解析 URL 中的域名部分(Host),它并不关心路径。比如对于下面这个地址:
1 | https://komiya.top/members |
我们可以将其拆分为:
- 域名:
komiya.top
✅ → DNS 要解析的正是它 - 路径:
/members
❌ → 与 DNS 无关,由服务器处理
换句话说,DNS 的职责仅仅是将域名变为 IP 地址。无论路径有多复杂,DNS 都不参与资源定位。只要在 DNS 记录中添加一条 komiya.top
的 A 记录(指向 IP 地址)或 CNAME 记录(指向另一个域名),客户端就能找到目标服务器。至于 /members
,那是 HTTP 请求发出之后,Web 服务器(如 Nginx、Apache)来处理的。
子域名
考虑另一个例子:
1 | https://ai.komiya.top |
ai.komiya.top
是一个子域名- 在 DNS 眼中,它是与
komiya.top
不同的完整域名 - 因此必须为它单独添加解析记录
例如:
ai.komiya.top →
添加 A 记录,指向某个服务器 IP- 或
ai.komiya.top →
添加 CNAME 记录,指向其他域名
这是容易混淆的点:子域名不是路径的延伸,而是完整域名的延伸,需要 DNS 单独配置。
域名的“等级制度”:从右往左分级
域名是从右向左分级的,每一个点(.
)都是层级的分隔符。DNS 解析也是遵循这种层级结构:
1 | www.example.com |
级别 | 名称 | 说明 |
---|---|---|
.com |
顶级域(TLD) | 通用后缀,由 ICANN 授权顶级 DNS 管理 |
example |
二级域名(主域) | 通常由用户注册获得 |
www |
三级域名(子域名) | 一般用于网站服务,实际可自定义 |
在这条结构中,.com
是顶层,www
是最底层。这种从右往左的结构决定了 DNS 查询也要逐级向上请求,直到获得正确的记录。
子域名可以无限嵌套,但有代价
理论上可以设置很多级别的子域名,比如:
1 | jojo.miaomiao.xxx.komiya.top |
只要你拥有 komiya.top
,你就可以添加任意子域。但实际部署中:
- HTTPS 证书(尤其是通配符证书)通常只能覆盖一级子域,例如
*.komiya.top
覆盖不了a.b.komiya.top
- 管理太多子域复杂度高,且难以统一认证与路由
- 浏览器或中间网络设备对极多级域名支持不佳
因此,实际中常见的就是最多一级子域名,例如:
www.example.com
api.example.com
blog.example.com
为什么总是看到 www
?
www.
其实没有任何技术强制,它不是保留字,而是历史习惯。
早期的网站会将 Web 服务部署在 www
子域上,以区分其他服务(如 mail.
, ftp.
)。虽然现在你完全可以用裸域名 example.com
来建站,但很多网站依然同时支持:
example.com
www.example.com
并通过 301 重定向 统一访问入口。
Web 服务器:路径由我守护
完成 DNS 解析后,浏览器已经知道了服务器的 IP 地址。那么下一步,就是将请求发送到目标主机。那么,如何根据请求中所带的“路径”来返回正确的网页或数据呢?这就是Web 服务器登场的时刻。
域名指向谁,路径交给谁
以访问如下网页为例:
1 | https://komiya.top/toy |
第一步:浏览器会提取 URL 中的域名 komiya.top
,通过 DNS 解析得到服务器的 IP 地址,例如:
1 | komiya.top → 123.45.67.89 |
这个解析过程由浏览器或操作系统调用本地 DNS 缓存或远程 DNS 服务器完成。
第二步:请求发出,抵达服务器。这时负责响应的是运行在目标主机上的Web 服务器程序,如 Nginx 或 Apache。它会根据请求的内容来决定返回什么。
Web 服务器如何处理请求?
Web 服务器在收到请求后,首先会检查 HTTP 请求中的 Host
头,例如:
1 | Host: komiya.top |
然后它会把这个 Host
值与自身的配置文件中的 server_name
进行匹配,找出应该由哪个“虚拟主机配置”来处理该请求。
一个典型的 Nginx 配置示例
假设我们使用了宝塔面板部署个人网站,它默认使用的是 Nginx,那么可能会看到这样的配置:
1 | server { |
配置说明:
配置项 | 说明 |
---|---|
listen 80; |
监听 80 端口(HTTP 默认端口) |
server_name |
匹配的域名,可同时支持裸域和子域名 |
root |
网站的根目录,对应资源路径 / 实际指向的本地文件路径 |
index |
默认首页文件名 |
location / |
定义对所有路径的匹配策略 |
try_files |
按顺序尝试访问对应文件,找不到则返回 404 |
举个实际的例子
访问:
1 | https://komiya.top/toy/jojo.txt |
浏览器实际上会发送一个 HTTP 请求,请求的路径是:
1 | /toy/jojo.txt |
按照上方 Nginx 的配置,这个请求 /toy/jojo.txt
会被映射为服务器本地文件路径:
1 | /www/wwwroot/komiya.top/toy/jojo.txt |
也就是说,请求路径 /toy/jojo.txt
被拼接到 root
指定的本地路径后面,形成完整的实际路径。对于这种情况,是文件,Nginx 就会直接返回文件。对于其他情况,根据配置则会有相应不同的处理:
请求路径 | 拼接路径 | 实际查找位置 |
---|---|---|
/ |
/www/wwwroot/komiya.top/ |
默认返回 index.html / index.php |
/toy |
/www/wwwroot/komiya.top/toy |
是文件就返回,是目录就尝试找 index 文件 |
/toy/jojo.txt |
/www/wwwroot/komiya.top/toy/jojo.txt |
找到就返回文件,找不到就返回 404 |
这里也可以看到,客户端看到的目录结构和实际服务器中存储的文件目录结构是不同的。Web 服务器内部将实际的目录名和供外部访问的虚拟目录名进行关联,这个映射规则是由 root
字段决定的。
虚拟主机与多个站点共存
通过 server_name
和不同的 server
块,Nginx 可以在同一台服务器上托管多个网站(虚拟主机)。例如:
1 | server { |
这样你就可以通过不同的子域名,部署不同的应用或网站,互不干扰。
宝塔面板
在使用 宝塔面板 管理网站时,每新增一个站点,其实就是在为 Nginx 创建一个新的配置文件。从面板中可以看到这样的界面(如下图所示),列出了我们所管理的所有网站:
每一行代表一个“站点”,每个站点都对应:
- 一个域名(或多个)
- 一个根目录(
root
) - 一份独立的 Nginx 配置文件
这些配置文件位于服务器中 /www/server/panel/vhost/nginx/
目录下,文件名通常就是我们添加的主域名,例如:
1 | /www/server/panel/vhost/nginx/komiya.top.conf |
宝塔面板为我们做了什么?
- 自动生成配置文件
- 自动为
server_name
填写输入的域名(含子域名) - 自动设置站点根目录(
root
) - 可选开启 PHP、SSL、重定向等功能
我们也可以在面板中可视化编辑 Nginx 配置,对于不熟悉命令行的用户特别友好。
举例说明:添加一个新站点会发生什么?
假设我们在宝塔中添加了站点:
- 主域名:
toy.komiya.top
- 根目录:
/www/wwwroot/toy
宝塔会自动生成如下配置:
1 | server { |
如果我们开启了 HTTPS,还会额外生成一个监听 443
的配置段,并自动绑定 SSL 证书。虽然我们可以在宝塔中添加多个网站,但本质上所有站点都是共用一个 Nginx 进程,彼此通过 server_name
区分配置。这也正是 Nginx 所谓的“虚拟主机”机制。
小结
通过本文,我们回顾了一次典型 Web 请求从「地址栏」到「页面显示」的幕后旅程。
- URL 是访问资源的入口,其中的域名和路径分别由不同系统组件负责处理;
- DNS 负责解析域名,将人类可读的地址(如
komiya.top
)转化为服务器 IP 地址,完成「找路」的工作; - Web 服务器(如 Nginx)收到请求后,根据配置文件,识别 Host 和路径,将请求路由到对应的目录或程序上,最终返回页面内容;
- 在使用可视化工具如宝塔面板时,每新增一个站点,其实就是背后增加了一个独立的 Nginx 配置文件,从而实现多站点共存;
- 子域名与路径看似相似,实则分别属于不同处理层面:子域名由 DNS 管控,路径由 Web 服务器解析。
理解这一流程,能帮助我们搭建网站、部署服务。