程序员

对 Web 请求过程的理解

  当我们从浏览器输入某个域名(如:http://www.baidu.com ),到服务器返回结果给浏览器为止,这个过程究竟发生了什么,又涉及到了哪些技术。本文谈谈自己对这一过程的理解。

1. B/S 网络总体结构

  目前 B/S 网络的总体架构大概如下图所示:

图 1. B/S 网络架构图

  当一个用户在浏览器输入 http://www.baidu.com 这个 URL 时,首先浏览器会请求 DNS 把这个域名解析成对应的 IP 地址 ,然后根据这个 IP 地址找到对应的服务器,向目标服务器发起一个 get 请求,由这个目标服务器决定返回什么数据资源给访问的用户。在这个过程中,服务器端还有很多复杂的业务逻辑:服务器可能不止一台,到底有哪台服务器来处理这个请求,这需要一个负载均衡设备来平均分配所有的用户请求;还有请求的数据可能存在分布式缓存里,也可能存在静态文件里,还有可能存在数据库;当数据返回给浏览器时,浏览器发现含有一些静态资源时,浏览器又会发起另外的 HTTP 请求,而这些请求很可能会在 CDN 上,CDN 服务器又会处理这些请求。这个过程中的每一个细节都会决定这个请求是否成功。

2. 如何发起一个 HTTP 请求

  发起一个 HTTP 请求和建立一个 Socket 连接的区别不大,只不过 outputStream.write 写的二进制数据格式要符合 HTTP。浏览器在建立 Socket 连接之前,必须根据地址栏输入的 URL 的域名 DNS 解析出 IP 地址,再根据这个 IP 地址和默认的80端口远程服务器建立 Socket 连接,然后浏览器根据这个 URL 组装成一个 get 类型的 HTTP 请求头,通过 outputStream.write 发送到目标服务器,服务器等待 inputStream.read 返回数据,最后断开这个连接。

3. 如何解析 HTTP

  这里只介绍下常用的 HTTP 请求头、响应头、状态码以及缓存机制。

请求头 说明
Accept-Charset 用于指定客户端接受的字符集
Accept-Encoding 用于指定可接受的内容编码,如 Accept-Encoding:gzip.deflate
Accept-Language 用于指定一种自然语言,如 Accept-Language:zh-cn
Host 用于指定被请求资源的 Internet 主机和端口号,如 Host:www.baidu.com
User-Agent 客户端将它的操作系统、浏览器和其他属性告诉服务器
Connection 当前连接是否保持,如:Connection:Keep-Alive
响应头 说明
Server 使用的服务器名称,如 Server:Apache/1.3.6(Unix)
Content-Type 用来指明发送给接受者的实体正文的媒体类型,如 Content-Type:text/html;charset=GBK
Content-Language 描述了资源所用的自然语言,与 Accept-Language 对应
Content-Encoding 与请求报头 Accept-Encoding 对应,告诉浏览器服务端采用的是什么压缩编码
Content-Length 指明实体正文的长度,用以志杰方式存储的十进制数字来表示
Keep-Alive 保持连接的时间,如:Keep-Alive: timeout=5, max=120
状态码 说明
200 客户端请求成功
302 临时跳转,跳转的地址通过 Location 指定
400 客户端请求有语法错误,不能被服务器识别
403 服务器收到请求,但是拒绝提供服务
404 请求的资源不存在
500 服务器发生不可预期的错误
缓存设置 说明
Cache-Control 请求字段优先级较高,使用如 Cache-Control: no-cache
Pragma 和 Cache-Control 作用类似,最常用的是 Pragma: no-cache
Expires Expires 后面跟着一个日期和时间,超过这个时间缓存的内容将失效
Last-Modified 服务器上的资源最后修改时间
Etag 服务端给每个页面分配一个唯一的编号,通过编号来区分当前页面是否是最新的

4. DNS 域名解析的过程

  DNS 域名解析的大致过程如下图所示:

图 2. DNS 域名解析

  1. 浏览器会检查缓存中是否有该域名对应的 IP 地址解析结果,如果缓存中有,这个解析过程就将结束。
  2. 如果用户的浏览器缓存中没有,浏览器会查找操作系统缓存中是否有这个域名对应的 DNS 解析结果。
  3. 如果用户操作系统缓存中没有,操作系统会把这个域名发送给 LDNS,也就是本地区的域名服务器。
  4. 如果 LDNS 仍然没有命中,就直接到 Root Server 域名服务器请求解析。
  5. 根域名服务器返回给本地域名服务器一个所查询域的主域名服务器(gTLD Server)地址。
  6. 本地域名服务器(LDNS)再向上一步返回的 gTLD 服务器发送请求。
  7. 接受请求的 gTLD 服务器查找并返回此域名对应的 Name Server 域名服务器地址,这个 Name Server 通常就是你注册的域名服务器。
  8. Name Server 域名服务器会查询存储的域名和 IP 的映射关系表,在正常情况下都根据域名得到目标 IP 记录,连同一个 TTL 指返回给 DNS Server 域名服务器。
  9. 返回该域名对应的 IP 和 TTL 值,LDNS 会缓存这个域名和 IP 的对应关系,缓存的时间由 TTL 值控制。
  10. 把解析的结果返回给用户,用户根据 TTL 值缓存在本地系统缓存中,域名解析过程到此结束。

5. 几种域名解析方式

  • A 记录:A 代表的是 Address,用来指定域名对应的 IP 地址。
  • MX 记录:表示的是 Mail Exchange,就是可以将某个域名下的邮件服务器指向自己的 Mail Server。
  • CNAME 记录:全称是 Canonical Name(别名解析),就是可以为一个域名设置一个或者多个别名。
  • NS 记录:为某个域名指定 DNS 解析服务器。
  • TXT 记录:为某个主机名或域名设置说明。

6. 何谓 CDN

  CDN 也就是内容分布网络(Content Delivery Network),目的就是使用户可以就近取得所需的内容,提高用户访问网络的响应速度。