知识地图

HTTP 是什么

HyperText Transfer Protocol 超文本传输协议,是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。

HTTP 跑在 TCP/IP 协议栈之上,依靠 IP 协议实现寻址和路由、TCP 协议实现可靠数据传输、DNS 协议实现域名查找、SSL/TLS 协议实现安全通信。此外,还有一些协议依赖于 HTTP,例如 WebSocket、HTTPDNS 等。

协议内容

URI

格式:{协议}://{域名/IP}:{端口号}{路径}?query

统一资源标识符Uniform Resource Identifier),使用ASCII 码,会把非 ASCII 码或特殊字符转换成十六进制字节值,然后前面再加上一个“%”。例如,空格被转义成“%20”,“?”被转义成“%3F”。而中文、日文等则通常使用 UTF-8 编码后再转义,例如“银河”会被转义成“%E9%93%B6%E6%B2%B3”。

特殊字符(保留字符)

  • :(冒号):用于分隔 URI 的不同部分,例如在 http://example.com 中,: 用于分隔协议名和主机名。
  • /(斜杠):用于表示路径分隔符,如 http://example.com/path/to/resource 中的 /
  • ?(问号):用于分隔路径和查询字符串,如 http://example.com/search?query=example
  • #(井号):用于标识 URI 中的片段,如 http://example.com/page.html#section1
  • [ 和 ](方括号):在 IPv6 地址中使用,例如 http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/
  • @(at 符号):用于分隔用户名和主机名,在邮件地址或某些特殊的 URI 格式中使用。

编码方式

URI 编码通常采用百分号编码(Percent-Encoding),即将需要编码的字符替换为 % 后面跟着该字符的 ASCII 码的两位十六进制表示。例如,空格的 ASCII 码是 32,十六进制表示为 20,所以空格会被编码为 %20

域名

为了方便记忆,所以发明了域名,通过域名可以找到对应的 IP 地址。

一个完整的域名通常由多个部分组成,从右到左依次为顶级域名、二级域名、三级域名等,各部分之间用点分隔。例如,在域名 www.example.com 中:

  • 顶级域名(TLD,Top – Level Domain):位于域名的最右侧,分为通用顶级域名(gTLD)和国家或地区顶级域名(ccTLD)。
    • 通用顶级域名:如 .com(商业机构)、.org(非营利组织)、.net(网络服务提供商)、.edu(教育机构)等。
    • 国家或地区顶级域名:代表不同的国家或地区,如 .cn(中国)、.us(美国)、.uk(英国)等。
  • 二级域名:位于顶级域名的左侧,是由域名注册者自行定义的名称,用于标识特定的组织、网站或服务。例如,在 example.com 中,example 就是二级域名。
  • 三级域名及以下:在二级域名的基础上,可以进一步细分,形成三级域名、四级域名等。例如,www.example.com 中的 www 通常是一个常见的三级域名,用于表示万维网服务。

DNS

域名解析是将域名转换为对应的 IP 地址的过程,主要通过 DNS 系统来完成。DNS 系统是一个分布式的数据库,由多个 DNS 服务器组成,负责存储和管理域名与 IP 地址的映射关系。域名解析的基本流程如下:

  1. 客户端发起请求:当用户在浏览器中输入域名并回车后,浏览器会向本地 DNS 服务器发送域名解析请求。
  2. 本地 DNS 服务器查询:本地 DNS 服务器首先检查自己的缓存中是否有该域名的解析记录。如果有,则直接返回对应的 IP 地址;如果没有,则向根 DNS 服务器发送查询请求。
  3. 根 DNS 服务器响应:根 DNS 服务器返回负责该顶级域名的 DNS 服务器的地址。
  4. 顶级域名 DNS 服务器查询:本地 DNS 服务器根据根 DNS 服务器返回的地址,向负责该顶级域名的 DNS 服务器发送查询请求,获取负责该二级域名的 DNS 服务器的地址。
  5. 权威 DNS 服务器查询:本地 DNS 服务器向负责该二级域名的权威 DNS 服务器发送查询请求,获取该域名对应的 IP 地址。
  6. 返回结果:本地 DNS 服务器将获取到的 IP 地址返回给客户端浏览器,浏览器使用该 IP 地址与服务器建立连接,获取相应的网页内容。

报文

报文是在 HTTP 协议中,客户端和服务器之间进行通信时所传输的数据块。HTTP 协议规定报文必须有 header,但可以没有 body,而且在 header 之后必须要有一个“空行”,也就是“CRLF”,十六进制的“0D0A”。

请求报文

POST /login HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

username=john&password=123456

请求行由三部分构成:

  1. 请求方法:是一个动词,如 GET/POST,表示对资源的操作;
  2. 请求目标:通常是一个 URI,标记了请求方法要操作的资源;
  3. 版本号:表示报文使用的 HTTP 协议版本。

Host:指定请求的目标主机和端口号,是 HTTP/1.1 协议中必须包含的字段

User-Agent:标识客户端的类型和版本信息,服务器可以根据该信息为不同的客户端提供不同的服务。

Accept:指定客户端可以接受的响应内容类型,用 MIME 类型表示。

Accept-Language:指定客户端可以接受的自然语言,服务器可以根据该信息返回相应语言的内容。

Accept-Encoding:指定客户端可以接受的响应内容编码方式,如 gzipdeflate 等。

Cookie:用于在客户端和服务器之间传递会话信息,服务器可以根据 Cookie 识别用户身份。

Content-Type:指定请求体的内容类型,用 MIME 类型表示。

Content-Length:指定请求体的字节长度。

响应报文

HTTP/1.1 200 OK
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Content-Length: 123

<!DOCTYPE html>
<html>
<head>
    <title>Welcome</title>
</head>
<body>
    <h1>Welcome to our website!</h1>
</body>
</html>

比起请求行来说,状态行要简单一些,同样也是由三部分构成:

  1. 版本号:表示报文使用的 HTTP 协议版本;
  2. 状态码:一个三位数,用代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;
  3. 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。

头部字段 Header

请求头和响应头的结构是基本一样的,唯一的区别是起始行,所以我把请求头和响应头里的字段放在一起介绍。

头部字段是 key-value 的形式,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字段结束。比如在“Host: 127.0.0.1”这一行里 key 就是“Host”,value 就是“127.0.0.1”。

HTTP 头字段非常灵活,不仅可以使用标准里的 Host、Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。

不过使用头字段需要注意下面几点:

  1. 字段名不区分大小写,例如“Host”也可以写成“host”,但首字母大写的可读性更好;
  2. 字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线“_”。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;
  3. 字段名后面必须紧接着“:”,不能有空格,而“:”后的字段值前可以有多个空格;
  4. 字段的顺序是没有意义的,可以任意排列不影响语义;
  5. 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。

Date:表示响应生成的日期和时间。

Server:标识服务器的类型和版本信息。

Set-Cookie:用于在客户端设置 Cookie,服务器可以通过该字段将会话信息存储在客户端。

ETag:是资源的唯一标识符,用于缓存验证。客户端可以通过比较 ETag 来判断资源是否有更新。

实体数据

HTTP 实体数据是 HTTP 消息(请求或响应)中的重要组成部分,它承载了客户端与服务器之间传输的实际内容,比如网页的 HTML 代码、图片、视频、文本信息等。

相关头部字段
  • Content-Type:该字段用于指定实体数据的媒体类型(MIME 类型),常见的值有 text/html(表示 HTML 文档)、application/json(表示 JSON 数据)、image/jpeg(表示 JPEG 图片)、application/pdf(表示 PDF 文档)等。例如 Content-Type: application/json 表示实体数据是 JSON 格式。
  • Content-Length:用于指定实体数据的长度,以字节为单位。服务器可以通过这个字段告诉客户端响应内容的大小,客户端也可以用它来告知服务器发送的请求体的长度。如 Content-Length: 1234 表示实体数据长度为 1234 字节。
  • Content-Encoding:指示实体数据的编码方式,常见的有 gzipdeflatebr 等。使用压缩编码可以减小数据传输量,提高传输效率。比如 Content-Encoding: gzip 表示数据采用了 gzip 压缩。
数据格式
  • 文本格式:如 HTML、CSS、JavaScript、JSON、XML 等文本数据。以 JSON 为例,数据可能像这样:{"name": "John", "age": 30}
  • 二进制格式:用于传输图片、音频、视频、可执行文件等非文本数据。这些数据以二进制的形式在 HTTP 连接中传输,客户端接收到后会根据相应的文件格式进行解析和处理。
  • 表单数据格式:当通过 HTML 表单提交数据时,通常有两种常见的格式。一种是 application/x-www-form-urlencoded,数据会被编码成键值对的形式,例如 username=john&password=123456。另一种是 multipart/form-data,用于上传文件或包含多个部分的表单数据,每个部分都有自己的头部信息和数据内容,常用于文件上传等场景。
传输与处理
  • 传输:HTTP 实体数据在客户端和服务器之间通过 TCP 连接进行传输。服务器将实体数据按照一定的规则分块或者一次性发送给客户端,客户端则根据接收到的数据和相关头部字段的信息来解析和处理数据。如果采用了分块传输编码,数据会被分成多个数据块进行传输,每个数据块都有长度标识。
  • 处理:客户端收到 HTTP 响应后,会根据 Content-Type 等头部字段来确定如何处理实体数据。如果是 HTML 数据,浏览器会解析并渲染成网页;如果是 JSON 数据,客户端的脚本可以将其解析为 JavaScript 对象进行处理;对于图片等二进制数据,浏览器会将其显示为图像。在服务器端,当接收到客户端的请求包含实体数据时,服务器会根据请求的 Content-Type 和业务逻辑来解析和处理数据,比如将表单数据插入数据库,对上传的文件进行存储等。
示例

text/plain

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 26

This is a plain text example.

text/html

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 121

<!DOCTYPE html>
<html>
<head>
    <title>Example Page</title>
</head>
<body>
    <h1>Hello, World!</h1>
</body>
</html>

image/jpeg

HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 12345

[二进制图像数据,无法直接显示]

application/json

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 25

{
    "message": "Data received"
}

application/xml

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 45

<response>
    <status>Success</status>
</response>

application/x-www-form-urlencoded

POST /submit-form HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 23

username=user&password=pass

multipart/form-data

POST /upload-file HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=---------------------------1234567890
Content-Length: 234

-----------------------------1234567890
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

This is the content of the file.
-----------------------------1234567890--

请求方法

  • GET
    用于从服务器获取资源。这是最常用的请求方法,当你在浏览器的地址栏输入一个 URL 并回车时,浏览器通常会发送一个 GET 请求到服务器,以获取对应的网页、图片、文件等资源。参数可见、有长度限制
  • POST
    用于向服务器提交数据,通常用于创建新的资源,如提交表单数据、上传文件等。参数不可见、无长度限制
  • PUT
    用于向服务器上传资源,通常用于更新已存在的资源。如果指定的资源不存在,服务器可能会创建该资源。
  • DELETE
    用于请求服务器删除指定的资源。
  • HEAD
    与 GET 请求类似,但服务器只返回响应头,不返回响应体。常用于获取资源的元信息,如资源的大小、修改时间、内容类型等,而不需要获取整个资源。
  • OPTIONS
    用于获取服务器支持的请求方法和其他相关信息。客户端可以通过发送 OPTIONS 请求,了解服务器对特定资源所支持的请求方法、请求头字段等。
  • PATCH
    用于对资源进行部分更新,与 PUT 请求不同,PUT 请求会替换整个资源,而 PATCH 请求只更新资源的部分属性。

响应状态码

HTTP 返回码(HTTP Status Code)是服务器返回给客户端的三位数字代码,用于表示 HTTP 请求的结果。这些状态码可以分为五大类,每一类都有不同的含义,以下是详细介绍,服务器可自定义返回的状态码的描述。

  • 1XX:信息性状态码
    这类状态码表示临时的响应,通常用于告知客户端请求已被接收,正在进一步处理中。
    • 100 Continue
      客户端在发送包含 Expect: 100 - continue 请求头的请求后,如果服务器愿意接受后续的数据,就会返回此状态码,告知客户端可以继续发送请求体。例如,当客户端需要上传一个大文件时,为了避免在服务器不接受该请求的情况下浪费带宽和时间,会采用这种方式
    • 101 Switching Protocols
      当客户端通过 Upgrade 请求头请求服务器切换协议时,如果服务器同意切换,就会返回此状态码,并在响应头中包含 Upgrade 字段,指定新的协议
  • 2XX 成功状态码
    表示服务器成功处理了客户端的请求
    • 200 OK
    • 201 Created
      表示服务器已经成功处理了请求,并且创建了一个新的资源。通常在使用 POST 方法创建新资源,或者 PUT 方法更新资源并创建了新的版本时返回。
    • 202 Accepted
      表示服务器已经接受了客户端的请求,但尚未处理完成。这个状态码通常用于异步操作,服务器接收到请求后,会在后台进行处理,客户端可以通过其他方式(如轮询)来获取处理结果。
    • 204 No Content
      表示服务器成功处理了请求,但没有返回任何内容。通常用于只需要服务器执行某个操作,而不需要返回数据的情况,比如删除操作或者更新操作成功后,可能不需要返回具体的数据。
    • 206 Partial Content
      表示服务器已经成功处理了部分 GET 请求。客户端可以通过在请求头中使用 Range 字段来指定获取资源的部分内容,服务器根据请求返回相应的部分内容,并返回 206 Partial Content 状态码。
  • 3XX 重定向状态码
    用于告知客户端需要采取进一步的操作来完成请求,通常是将请求重定向到另一个 URL
    • 301 Moved Permanently(永久重定向)
      搜索引擎在遇到 301 重定向时,会更新其索引,将旧的 URL 替换为新的 URL,同时会把旧 URL 的权重传递给新 URL。场景:网站改版、业务调整
    • 302 Found(临时重定向)
      搜索引擎不会更新其索引,也不会将旧 URL 的权重传递给新 URL。场景:网站维护、A/B Test
    • 303 See Other(另请参阅)
    • 304 Not Modified(未修改)
      表示客户端的缓存仍然有效,服务器没有对请求的资源进行修改。客户端可以使用本地缓存的资源,而不需要再次从服务器下载。这个状态码通常与缓存机制相关,用于减少不必要的数据传输。
    • 307 Temporary Redirect(临时重定向)
       302 Found 类似,表示请求的资源临时移动到了新的 URL。但与 302 不同的是,307 重定向会保留原请求的方法和请求体。也就是说,如果原请求是 POST 请求,重定向后的请求仍然是 POST 请求。
    • 308 Permanent Redirect(永久重定向)
      与 301 Moved Permanently 类似,表示请求的资源已经永久移动到了新的 URL。但与 301 不同的是,308 重定向会保留原请求的方法和请求体。也就是说,如果原请求是 POST 请求,重定向后的请求仍然是 POST 请求。
  • 4XX 客户端错误状态码
    客户端的请求可能存在错误,导致服务器无法处理该请求
    • 400 Bad Request(错误请求)
      表示客户端发送的请求存在语法错误,无法被服务器理解。这可能是由于请求参数格式错误、请求头缺失或格式不正确等原因造成的。场景:参数错误、JSON 解析错误
    • 401 Unauthorized(未授权)
      表示请求需要进行身份验证,而客户端没有提供有效的身份验证信息。服务器通常会在响应头中包含 WWW - Authenticate 字段,指定身份验证的方式。场景:登录验证、API 访问
    • 403 Forbidden(禁止访问)
      意味着服务器理解客户端的请求,但拒绝执行该请求。客户端可能已经通过身份验证,但没有权限访问请求的资源。场景:权限不足、IP 封禁
    • 404 Not Found(未找到)
    • 405 Method Not Allowed(方法不允许)
    • 406 Not Acceptable(不可接受)
    • 408 Request Timeout(请求超时)
      表示服务器在等待客户端发送请求的过程中超时。这可能是由于网络延迟、客户端故障等原因导致的。场景:网络问题
    • 429 Too Many Requests
      表示客户端在一定时间内发送了过多的请求,触发了服务器的请求速率限制机制
  • 5XX 服务器错误状态码
    服务器在处理请求时发生错误
    • 500 Internal Server Error(内部服务器错误)
      场景:代码逻辑错误、数据库连接问题等
    • 501 Not Implemented(未实现)
      表示服务器不支持客户端请求的功能或方法。也就是说,客户端使用了服务器尚未实现的请求方法或特性。
    • 502 Bad Gateway(错误网关)
      通常发生在服务器作为网关或代理时,从上游服务器(如后端应用服务器)接收到了无效的响应。这意味着网关或代理服务器本身正常,但无法从上游服务器获取有效的数据。场景:上游服务器故障、网络连接问题
    • 503 Service Unavailable(服务不可用)
      表示服务器目前无法处理请求,通常是由于服务器过载、正在进行维护或出现临时故障等原因导致的。服务器可能会在响应头中包含 Retry - After 字段,指定客户端可以在多长时间后重试请求。场景:高并发请求、服务器维护
    • 504 Gateway Timeout
      表示作为网关或代理的服务器在等待上游服务器的响应时超时。这意味着网关服务器已经将请求转发给了上游服务器,但在规定的时间内没有收到上游服务器的响应。场景:上游服务器响应慢、网络延迟
    • 505 HTTP Version Not Supported(HTTP 版本不支持)
      表示服务器不支持客户端请求中使用的 HTTP 协议版本。例如,客户端使用了较新的 HTTP/3 协议,而服务器只支持 HTTP/1.1 或 HTTP/2。场景:服务器配置问题、版本兼容性问题

缓存

HTTP 缓存是一种机制,用于减少对服务器的请求,提高网站性能和响应速度,降低服务器负载。它可以存储已经访问过的资源副本,当再次请求相同资源时,直接从缓存中获取,而不必重新从服务器下载。以下将从缓存类型、控制缓存的首部字段、缓存验证等方面详细介绍 HTTP 缓存。

服务器的缓存控制

客户端的缓存控制

缓存类型

强缓存

强缓存是指浏览器直接从本地缓存中读取资源,而无需向服务器发送请求。判断资源是否使用强缓存主要依据 Expires 和 Cache-Control 这两个首部字段。

  • Expires:这是 HTTP/1.0 中用于控制缓存的字段,它的值是一个具体的时间点(GMT 格式),表示资源的过期时间。例如:
Expires: Thu, 31 Dec 2025 23:59:59 GMT

在这个时间之前,浏览器会直接使用本地缓存的资源。不过,由于它依赖于客户端的系统时间,如果客户端时间设置不准确,可能会导致缓存失效或资源未及时更新。

  • Cache-Control:这是 HTTP/1.1 中用于控制缓存的主要字段,它的优先级高于 Expires。可以设置多个指令,常见的指令如下:
    • max-age:指定资源的缓存时间,单位为秒。例如:
Cache-Control: max-age=3600

表示资源在 3600 秒(1 小时)内有效,在此期间浏览器会直接使用本地缓存。

  • no-cache:表示需要先向服务器验证资源是否有更新,然后再决定是否使用缓存。
  • no-store:表示禁止使用任何缓存,每次请求都要从服务器获取最新资源。
  • public:表示资源可以被任何缓存(包括客户端和代理服务器)缓存。
  • private:表示资源只能被客户端缓存,代理服务器不能缓存。

协商缓存

当强缓存失效时,浏览器会向服务器发送请求,通过与服务器协商来判断资源是否有更新。如果资源没有更新,服务器会返回 304 状态码,浏览器可以使用本地缓存;如果资源有更新,服务器会返回 200 状态码和新的资源。协商缓存主要依据 ETag 和 Last-Modified 这两个首部字段。

  • Last-Modified:服务器在响应头中添加 Last-Modified 字段,它的值是资源的最后修改时间。例如:
Last-Modified: Wed, 22 Jan 2025 12:00:00 GMT

当浏览器再次请求该资源时,会在请求头中添加 If-Modified-Since 字段,其值为上次响应中 Last-Modified 的值。服务器会比较资源的当前修改时间和 If-Modified-Since 的值,如果相同则返回 304 状态码,否则返回新的资源。不过,Last-Modified 存在一些局限性,比如它只能精确到秒级,如果在一秒内资源多次修改,它无法准确判断资源是否有更新。

  • ETagETag 是服务器为资源生成的一个唯一标识符,通常是资源内容的哈希值。例如:
ETag: "123456789abcdef"

当浏览器再次请求该资源时,会在请求头中添加 If-None-Match 字段,其值为上次响应中 ETag 的值。服务器会比较当前资源的 ETag 和 If-None-Match 的值,如果相同则返回 304 状态码,否则返回新的资源。ETag 的优先级高于 Last-Modified,它可以更精确地判断资源是否有更新。

缓存验证流程

  1. 浏览器发起请求,首先检查本地缓存。
  2. 如果本地缓存中存在该资源,检查 Cache-Control 和 Expires 字段判断是否命中强缓存。如果命中强缓存,直接使用本地缓存,不向服务器发送请求。
  3. 如果未命中强缓存,检查本地缓存中是否有 Last-Modified 和 ETag 信息。如果有,在请求头中添加 If-Modified-Since 和 If-None-Match 字段,向服务器发送请求进行协商缓存验证。
  4. 服务器收到请求后,根据 If-Modified-Since 和 If-None-Match 的值判断资源是否有更新。如果资源没有更新,返回 304 状态码,浏览器使用本地缓存;如果资源有更新,返回 200 状态码和新的资源,并更新响应头中的 Last-Modified 和 ETag 信息。
  5. 如果本地缓存中没有 Last-Modified 和 ETag 信息,直接向服务器请求新的资源。
  • 对于静态资源:如图片、CSS、JavaScript 文件等,通常可以设置较长的缓存时间,使用强缓存,以提高性能。可以设置 Cache-Control: max-age=31536000(一年)。
  • 对于动态资源:如用户的个人信息页面、新闻列表等,建议使用协商缓存,以确保用户能够及时获取到最新的内容。可以设置 Cache-Control: no-cache

代理

HTTP 代理是一种网络代理服务,在客户端和服务器之间充当中间媒介,负责转发 HTTP 请求和响应。

所谓的“代理服务”就是指服务本身不生产内容,而是处于中间位置转发上下游的请求和响应,具有双重身份:面向下游的用户时,表现为服务器,代表源服务器响应客户端的请求;而面向上游的源服务器时,又表现为客户端,代表客户端发送请求。

作用

  • 负载均衡:决定由哪台服务器来响应请求;
  • 健康检查:使用“心跳”等机制监控后端服务器,发现有故障就及时“踢出”集群,保证服务高可用;
  • 安全防护:保护被代理的后端服务器,限制 IP 地址或流量,抵御网络攻击和过载;
  • 加密卸载:对外网使用 SSL/TLS 加密通信认证,而在安全的内网不加密,消除加解密成本;
  • 数据过滤:拦截上下行的数据,任意指定策略修改请求或者响应;
  • 内容缓存:暂存、复用服务器响应;

正向代理

  • 本地电脑配置网络代理
  • Chrome 浏览器安装SwitchyOmega 扩展

反向代理

Nginx 配置

server {
    listen 80;
    server_name yourdomain.com; # 替换为你的域名或 IP 地址

    location / {
        proxy_pass http://backend_server; # 替换为后端服务器的地址和端口
        proxy_set_header Host $host;
        proxy_set_header X - Real - IP $remote_addr;
        proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
    }
}
# 默认使用轮询算法进行负载均衡,也可以根据需要配置其他算法,如 IP 哈希、加权轮询等
upstream backend_server {
    server 192.168.1.100:8080;
    server 192.168.1.101:8080;
}

测试代理是否生效
访问网站,查看显示的 IP 地址是否为代理服务器的 IP。若显示的是代理服务器的 IP,表明代理已生效。

https://whatismyipaddress.com

分块传输/范围请求

范围请求允许客户端指定请求资源的部分内容,而不是整个资源。客户端通过在请求头中使用 Range 字段来指定所需的字节范围,服务器根据该范围返回部分内容,并在响应头中使用 Content-Range 字段指示返回内容的范围。这种方式适用于大文件的断点续传、多线程下载等场景。

适用场景

  • 大文件下载,用户可以暂停和恢复下载,或者使用多线程同时下载不同的部分,提高下载效率。
  • 媒体文件的流式播放,客户端可以根据需要请求特定范围的音频或视频数据。
GET /large_file.zip HTTP/1.1
Host: example.com
Range: bytes=1024-2047
HTTP/1.1 206 Partial Content
Content-Range: bytes 1024-2047/1048576
Content-Length: 1024
Content-Type: application/zip

[文件从第 1024 字节到第 2047 字节的内容]

优点

  • 断点续传
    • 支持客户端在下载过程中暂停和恢复下载,当网络中断或用户暂停下载后,下次可以从上次中断的位置继续下载,避免了重复下载已完成的部分,节省了时间和带宽。
  • 多线程下载
    • 客户端可以同时发起多个范围请求,使用多线程并行下载不同的字节范围,从而提高下载速度。例如,一个大文件可以被分成多个部分,每个线程负责下载一个部分,最后将这些部分合并成完整的文件。
  • 资源按需获取
    • 客户端可以根据自己的需求只请求资源的部分内容,而不是整个资源。对于大型媒体文件(如视频、音频)的流式播放,客户端可以根据播放进度请求特定范围的数据,减少不必要的数据传输,提高播放的流畅性。

缺点

  • 服务器处理复杂度增加
    • 服务器需要处理多个范围请求,解析 Range 请求头,根据请求范围读取和返回部分内容,增加了服务器的处理逻辑和复杂度。特别是在高并发情况下,服务器需要处理大量的范围请求,可能会影响性能。
  • 元数据管理开销
    • 服务器需要维护资源的元数据,如文件大小、字节范围等,以便正确处理范围请求。这增加了服务器的存储和管理开销,特别是对于大量的资源。
  • 潜在的数据不一致问题
    • 如果在客户端请求范围的过程中,服务器上的资源发生了变化(如文件被更新),可能会导致客户端获取的数据不一致。需要额外的机制来确保数据的一致性,增加了系统的复杂性。

四层协议/七层协议

在网络通信中,通常会用模型来描述网络的架构和数据传输过程,其中比较经典的是四层协议模型(TCP/IP 模型)和七层协议模型(OSI 模型)。HTTP 协议在这两个模型中处于不同的层次

  • OSI 模型:是由国际标准化组织(ISO)制定的一种理想化的网络通信标准模型,旨在为不同厂商的网络设备和软件提供一个统一的、标准化的框架,以实现互操作性。然而,由于其设计过于复杂,实现成本较高,在实际应用中并没有得到广泛的应用,但它为网络理论的研究和教学提供了重要的参考。
  • TCP/IP 模型:是在互联网发展过程中逐渐形成的,它是基于实际的网络需求和技术实现而设计的。由于其简单实用、易于实现,成为了互联网通信的事实标准,被广泛应用于各种网络设备和操作系统中,如路由器、交换机、计算机等。

四层协议模型(TCP/IP 模型)

从下到上分别是网络接口层、网络层、传输层和应用层

  • 网络接口层
    • 功能:负责物理连接和数据的传输,包括硬件设备(如网卡)和物理介质(如网线、光纤)的管理,以及将数据帧转换为物理信号进行传输。
    • 涉及协议:以太网协议、Wi – Fi 协议等。
  • 网络层
    • 功能:主要负责数据包的路由和转发,确定数据包从源地址到目标地址的最佳路径。
    • 涉及协议:IP 协议(Internet Protocol)、ICMP 协议(Internet Control Message Protocol)等。
  • 传输层
    • 功能:提供端到端的通信服务,确保数据的可靠传输。它可以处理数据的分段、排序、错误检测和重传等问题。
    • 涉及协议:TCP 协议(Transmission Control Protocol)和 UDP 协议(User Datagram Protocol)。HTTP 协议通常使用 TCP 协议进行数据传输,因为 TCP 提供可靠的、面向连接的服务,能保证 HTTP 请求和响应数据的完整传输。
  • 应用层
    • 功能:为用户提供应用程序接口,处理特定的应用程序协议,直接与用户的应用程序交互。
    • 涉及协议:HTTP 协议(Hypertext Transfer Protocol)、FTP 协议(File Transfer Protocol)、SMTP 协议(Simple Mail Transfer Protocol)等。HTTP 协议位于这一层,用于在 Web 浏览器和 Web 服务器之间传输超文本数据,如 HTML 页面、图片、JSON 数据等。

七层协议模型(OSI 模型)

从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层

  • 物理层
    • 功能:负责传输比特流,定义了物理介质的电气、机械和功能特性,如电缆的类型、接口的规格等。
    • 涉及协议:RS – 232 协议、Ethernet 物理层标准等。
  • 数据链路层
    • 功能:将物理层传输的比特流封装成数据帧,处理相邻节点之间的数据传输,包括错误检测和纠正、流量控制等。
    • 涉及协议:以太网协议、PPP 协议(Point – to – Point Protocol)等。
  • 网络层
    • 功能:与 TCP/IP 模型的网络层类似,负责数据包的路由和转发,确定数据包的最佳传输路径。
    • 涉及协议:IP 协议、ICMP 协议等。
  • 传输层
    • 功能:同样提供端到端的通信服务,确保数据的可靠传输,处理数据的分段、排序和错误恢复等问题。
    • 涉及协议:TCP 协议、UDP 协议。
  • 会话层
    • 功能:负责建立、管理和终止会话,协调不同主机之间的通信会话,处理会话的同步和恢复。
    • 涉及协议:NetBIOS 协议、RPC 协议(Remote Procedure Call)等。
  • 表示层
    • 功能:处理数据的表示和转换,如数据的加密、解密、压缩、解压缩等,确保不同系统之间的数据能够正确理解。
    • 涉及协议:SSL/TLS 协议(用于数据加密)、JPEG 协议(用于图像压缩)等。在 HTTP 通信中,如果使用 HTTPS,就会涉及到表示层的 SSL/TLS 协议进行数据加密。
  • 应用层
    • 功能:为用户提供应用程序接口,处理特定的应用程序协议,直接与用户的应用程序交互。
    • 涉及协议:HTTP 协议、FTP 协议、SMTP 协议等。HTTP 协议在 OSI 模型中也位于应用层,用于实现 Web 应用的通信。

跨域

在浏览器中,出于安全考虑,遵循同源策略(Same – Origin Policy)。同源是指两个 URL 的协议、域名和端口号都相同。如果一个请求的源(发起请求的页面)和目标资源的源不一致,就会产生跨域问题。例如,从 http://www.example1.com 页面请求 http://www.example2.com 的资源,就属于跨域请求。

产生原因:同源策略是浏览器为了保护用户信息安全而设立的。它限制了不同源的页面之间的资源共享和交互,防止恶意网站通过跨源请求获取其他网站的敏感信息。然而,在实际开发中,很多场景需要进行跨域数据交互,比如前后端分离开发时,前端和后端可能部署在不同的域名或端口上,这就产生了跨域问题。

解决方法:

  • CORS(Cross – Origin Resource Sharing)
  • JSONP
  • 代理服务器

版本

HTTP/0.9

  • 发布时间:1991 年。
  • 特点
    • 极其简单:它是 HTTP 协议的最初版本,功能非常有限。请求只能是一个简单的 GET 请求,并且请求中只包含一个单行的 ASCII 文本,指定要获取的资源路径,没有请求头。例如:GET /index.html
    • 无状态响应:服务器的响应也很简单,仅返回请求的 HTML 文档内容,没有响应头,响应完成后立即关闭连接。
    • 仅支持文本:主要用于传输 HTML 文本,不支持其他类型的数据,如图片、音频等。

HTTP/1.0

  • 发布时间:1996 年。
  • 特点
    • 请求和响应头:引入了请求头和响应头的概念,允许在请求和响应中包含更多的元信息,如 Content-Type 用于指定响应内容的类型,User-Agent 用于标识客户端的类型等。这使得 HTTP 协议可以处理更多类型的数据,如图片、音频、视频等。
    • 状态码:定义了一系列的状态码,用于表示请求的结果,如 200 OK 表示请求成功,404 Not Found 表示请求的资源不存在等。
    • 多种请求方法:除了 GET 请求,还支持 POST 方法,用于向服务器提交数据,为表单提交和数据上传提供了支持。
    • 非持久连接:默认情况下,每次请求都会建立一个新的 TCP 连接,请求完成后立即关闭连接。这种方式在处理多个请求时会带来较大的开销,因为建立和关闭连接需要一定的时间和资源。

HTTP/1.1

  • 发布时间:1999 年。
  • 特点
    • 持久连接:引入了持久连接的概念,即允许在一个 TCP 连接上发送多个请求和响应,避免了频繁建立和关闭连接的开销,提高了传输效率。可以通过在请求头中设置 Connection: keep - alive 来启用持久连接。
    • 请求方法扩展:增加了更多的请求方法,如 PUT 用于更新资源,DELETE 用于删除资源,HEAD 用于获取资源的头部信息等,使得 HTTP 协议可以更好地支持 RESTful 架构。
    • 分块传输编码:支持分块传输编码(Chunked Transfer Encoding),允许服务器在不知道响应内容长度的情况下,将响应数据分成多个块进行传输,客户端可以逐块接收和处理数据。
    • 缓存机制:完善了缓存机制,引入了更多的缓存控制头,如 Cache - ControlETag 等,使得客户端和服务器可以更好地控制资源的缓存和更新,减少不必要的数据传输。
    • 虚拟主机支持:支持在一个服务器上托管多个域名,通过 Host 请求头来指定请求的目标主机,使得服务器可以根据不同的域名提供不同的服务。

HTTP/2

  • 发布时间:2015 年。
  • 特点
    • 二进制分帧:HTTP/2 采用二进制分帧层,将请求和响应数据分割成更小的二进制帧进行传输,提高了传输效率和解析速度。帧是 HTTP/2 中最小的数据传输单位,每个帧都有自己的类型和标识符。
    • 多路复用:允许在一个 TCP 连接上同时并行处理多个请求和响应,不同的请求和响应可以交错传输,避免了 HTTP/1.1 中的队头阻塞问题,提高了连接的利用率。
    • 头部压缩:使用 HPACK 算法对请求和响应的头部进行压缩,减少了头部数据的传输量,降低了带宽消耗。
    • 服务器推送:服务器可以主动向客户端推送相关的资源,而不需要客户端显式地请求。例如,当客户端请求一个 HTML 页面时,服务器可以同时推送该页面所需的 CSS、JavaScript 和图片等资源,减少客户端的请求次数。

HTTP/3

解决队头阻塞问题:QUIC 协议在数据包层面解决了队头阻塞问题,即使某个数据包丢失,也不会影响其他流的传输,提高了传输的可靠性和效率。

发布时间:2022 年。

特点

基于 QUIC 协议:HTTP/3 基于 QUIC(Quick UDP Internet Connections)协议,取代了之前版本使用的 TCP 协议。QUIC 协议在 UDP 之上构建,具有更快的连接建立速度、更好的拥塞控制和抗丢包能力,减少了网络延迟。

进一步优化性能:继承了 HTTP/2 的优点,如二进制分帧、多路复用、头部压缩等,并通过 QUIC 协议进一步优化了性能,提供了更可靠、更快速的传输体验。

Web 服务器

Nginx

OpenResty

性能优化

压缩

CDN

抓包工具

Burb Suite

安全

SSL/TLS

WAF

总结

最后了解完上面的知识后,就可以轻松地回答下面的几个问题了

输入网址再按下回车,后面究竟发生了什么?

HTTPS 是如何确保安全的?

如何优化 web 网站性能?