应用层
HTTP 特征
- 简单快速:客户端向服务端发起请求的时候,只需要说明请求方法和请求路径
- 灵活:HTTP 允许传输任意类型的数据,只需要使用 Content-Type 标明
- 无状态:HTTP 没有记忆能力
HTTP 报文
HTTP 报文用于在客户端和服务端之间传送数据。HTTP 由请求(Request)和响应(Response)组成。
HTTP 报文由三大部分组成:
- 起始行:描述请求或响应的基本信息
- header:header 不能为空
- body:实际传输的数据,不一定是纯文本,也可以是视频、图片等。body 可以为空
通过 curl -v https://www.baidu.com 可以获得完整的请求报文、响应报文以及响应体。报文格式如下,报文每行由 \r\n 换行:
# 请求报文 # 首行由 Method Path Version 构成 # 每一行结尾是 \r\n GET / HTTP/1.1 # 以下是请求头,Host 是请求的域名 Host: www.baidu.com User-Agent: curl/7.79.1 Accept: */* # 响应报文 # 相隔两个 \r\n,将会收到响应报文 # 首行由 Version StatusCode 状态描述符组成 HTTP/1.1 200 OK # 以下是响应头 Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform Connection: keep-alive Content-Length: 2443 Content-Type: text/html Date: Wed, 31 Aug 2022 09:23:42 GMT Etag: "58860402-98b" Last-Modified: Mon, 23 Jan 2017 13:24:18 GMT Pragma: no-cache Server: bfe/1.0.8.18 Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/ # 响应体 # 相隔两个 \r\n,将会收到响应体 <!DOCTYPE html> ...
为什么使用 \r\n 作为换行呢?其实现在除了 Windows 把 \r\n 作为换行符,其他系统都是把 \n 作为换行符的。这里有一个有意思的背景:由于早期各个系统之间的换行符(LF、CR、CRLF、LFCR...)乱成一团,为了保证互联网的适用性,互联网之父们制定了一个规则:所有在互联网上传输的 ASCII 文本的换行符都必须遵守使用 CRLF(即 \r\n)作为换行符的规定,再由不同的操作系统将 CRLF 翻译为自己适用的换行符,这样让所有的操作系统平摊痛苦、避免吵架。
GET 和 POST 请求的区别
- 语义不同
- GET 参数放在 URL 后面,POST 放在报文实体中
- GET 安全幂等、POST 不安全不幂等(对于服务器来说),安全指是否会修改服务器上的资源、幂等指多次请求结果是否相同
- GET 提交的数据大小有限制,POST 无限制。注意:GET 本身并没有对数据长度进行限制,真正限制的是浏览器。对于不同的浏览器,GET 限制的长度可能不同
- GET 只支持 ASCII 字符,POST 无限制
- GET 一般会被缓存,POST 一般不会被缓存
HTTP 如何保存状态
前面说到,HTTP 是无状态协议,那如果我们需要保存登录态,可以怎样做呢?
- 基于 Session 实现会话保持:客户端第一次向服务端发送 HTTP 请求后,服务器创建 Session 并将客户端身份信息以键值对形式保存下来,然后分配一个 SessionId 给客户端。SessionId 一般会保存在客户端的 Cookie 中,之后每次浏览器的 HTTP 请求都会带上 Cookie 到服务器,服务器根据 Cookie 中的 SessionId 就可以知道用户是谁。优点:安全性高,因为状态保存在服务器端;缺点:因为大型网站用的是分布式服务器,多次 HTTP 请求可能落到不同的服务器上,这样基于 Session 的方法就不能实现会话保持了。当然我们可以把 Session 存储在 Redis 中,这样服务器就都可以访问到之前的状态信息了
- 基于 Set-Cookie 实现:服务器响应的时候在 HTTP 响应头设置 Set-Cookie 字段,用来存储客户端状态信息。客户端设置 Cookie 后,每次浏览器发送 HTTP 请求会带上 Cookie。这种方式相当于完全把状态信息存储在浏览器 Cookie 中。优点:服务端存储压力减小;缺点:不够安全,而且每次 Cookie 需要携带很多内容,占用更多带宽
如果 Cookie 禁用怎么办?我们可以重写 URL,比如 js 有函数 encodeURL()
状态码
分类 | 描述 |
---|---|
1xx | 请求正在处理 |
2xx | 请求成功处理 |
3xx | 重定向 |
4xx | 客户端错误 |
5xx | 服务端错误 |
常见状态码
状态码 | 英文描述 | 详细说明 |
---|---|---|
100 | Continue | 服务器收到了请求的一部分,并且希望客户端继续发送其余部分 |
101 | Switching Protocols | 切换协议,服务端根据客户端请求的头信息切换协议 |
200 | OK | 请求成功处理 |
201 | Created | 请求成功,并且创建了新的资源 |
202 | Accepted | 请求成功,但是还没有处理完成 |
204 | No Content | 请求成功,服务器处理了部分请求 |
301 | Moved Permanently | 永久重定向。请求的资源分配了新的 URL,之后应该使用更改的 URL |
302 | Found | 临时重定向。请求的资源被分配了新的 URL,希望本次访问使用新的 URL |
400 | Bad Request | 请求报文存在语法错误或者请求参数有误 |
401 | Unauthorized | 用户未授权或权限不足 |
403 | Forbidden | 服务器拒绝本次请求 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时了 |
500 | Internal Server Error | 服务器内部错误 |
502 | Bad Gateway | 服务器作为网关或代理,从远程服务器接收到了无效的响应 |
503 | Service Unavailable | 服务器超载或正在停机维护 |
301 和 302 的区别
定义 & 缓存
- 301:永久重定向。请求的资源已被永久的移动到新的 URI,旧的地址已经被永久的删除了。返回信息会包括新的 URI,浏览器会自动定向到新的 URI,今后新的请求都应使用新的 URI 代替。默认情况下这个响应是可缓存的
- 302:临时重定向。与 301 类似,客户端拿到服务端的响应消息后会跳转到一个新的 URL 地址。但资源只是临时被移动,旧的地址还在,客户端应继续使用原有 URI。302 的请求默认情况下是不缓存的,除非设置了 Cache-Control 或者 Expires
应用场景
- 301:一般情况下用户输入的地址都不带有协议。比如 www.baidu.com。在这种情况下,浏览器会假设你想要使用 HTTP 协议,然后发送一个 HTTP 请求到 www.baidu.com,然后服务端会返回 301 状态码将请求重定向到 HTTPS 站点
- 302:302 常用于用户登录的场景,比如说某个用户登录之前无法查看一些内容,会先跳转到登录界面,然后再回到原来的页面
搜索引擎
- 301:旧地址的资源不可访问了,重定向到新的网址,且将网址保存为新的网址
- 302:旧地址的资源依然可访问,只是这次抓取新网站的内容,网址依然保存原网址
HTTP/1.0
特性
- 引入了请求头和请求体,增加了状态码,支持多种文档类型
- 使用短连接,每次发送数据都要经过三次握手和四次挥手,效率低
- header 中只使用 If-Modified-Since 和 Expires 作为缓存
缺点
- 不支持断点续传
- 每个 IP 只能有一个域名
- 只有前面的请求返回才能进行下一次请求,效率很低
- 需要在响应头设置 Content-Length,然后浏览器再根据设置的数据大小来接收数据,对于动态生成的数据无能为力
- 存在带宽浪费现象,有时候客户端只是需要资源的一部分,服务端却全部都传了过来
HTTP/1.1
特性
- 缓存处理:HTTP/1.0 主要使用 If-Modified-Since,HTTP/1.1 增加了更多的请求头,如 ETag、If-Unmodified-Since、If-Match、If-None-Match
- Cookie:HTTP/1.1 引入了 Cookie
- 对动态生成的内容提供了完美的支持,通过 Transfer-Encoding: chunked 解决了这个问题。服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时都会附上数据块的长度,最后使用一个零长度的块作为发送数据完成的标志
- 支持断点续传
- 节约带宽:客户端请求资源的时候,HTTP/1.0 默认将该资源相关的整个对象都传送给请求方,但很多时候可能客户端并不需要对象的所有信息,而在 HTTP/1.1 的请求头中引入了 range,它允许只请求部分的资源
- Host 请求头:HTTP/1.0 中每台服务器只能绑定唯一的 IP 地址,而随着虚拟主机出现,一台物理服务器上可能存在多台虚拟主机,并且共享同一个 IP。为了支持虚拟主机,HTTP/1.1 添加了 Host 请求头,同时也支持一个 IP 对应多个域名
- 持久连接:默认开启持久连接,如果要兼容旧版本,需要加上 Connection: keep-alive
- Pipeline 管道:客户端传送过程不需要等待响应才能发起下一次请求
缺点
- 同时开启多条 TCP 连接时,连接之间会互相竞争带宽
- 队头阻塞:管道化要求服务端必须按照请求发送的顺序返回响应,如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达。HTTP/1.1 的队头阻塞问题是因为自身协议设计导致的
- 请求头重复携带
- 服务端永远处于被动
为什么 HTTP/1.1 不能实现多路复用?
HTTP/1.1 不是二进制传输,而是通过文本进行传输。由于没有流的概念,在使用并行传输(多路复用)传递数据时,接收端在接收到响应后,并不能区分多个响应分别对应的请求,所以无法将多个响应的结果重新进行组装,也就实现不了多路复用。
HTTP/1.1 可以如何优化?
- 尽量避免发送 HTTP 请求:使用缓存技术
- 在必须发送 HTTP 请求的时候,考虑如何减少请求的次数
- 合并请求:可以将多个小文件的请求合并为一个大的请求,虽然传输的总资源是一定的,但是减少了请求的次数,这就意味着减少了重复发送 HTTP 头部
- 延迟发送请求:比如图片懒加载
- 减少服务器 HTTP 响应的数据大小
HTTP/2.0
特性
- 完全的二进制协议。头和体都是二进制,而 HTTP/1.1 的头必须是 ASCII 编码
- 多路复用。在一个连接中,客户端和服务器都可以同时发送多个请求或回应,不需要按顺序发送
- 数据流概念。HTTP/2.0 的数据包是不按顺序发送的,同一个连接中的数据包可能来源于不同的请求,所以需要对数据包做标记,指明属于哪个请求。为了防止两端的 ID 冲突,客户端发起的流具有奇数的 ID,服务端发起的流具有偶数的 ID
- 头部压缩。因为 HTTP 无状态,每次请求都必须带上所有的信息,所以很多的请求字段都是重复的,比如 User-Agent。一模一样的内容每次请求都要携带会浪费带宽,影响速度。通过 gzip 或者 compress 压缩头后再发送。另一方面,客户端和服务端都维护一张头信息表,部分字段会存储到表中,生成一个索引,以后相同的就只发送索引,不发生字段,这也叫 HPACK 算法
- 允许服务器主动推送。HTTP/2.0 允许服务器未经请求,主动向客户端推送一些必要资源
缺点
TCP 数据包是有序传输的,如果中间一个数据包丢失,会等待该数据包重传,造成后面数据包的阻塞。队头阻塞主要是 TCP 协议的可靠性机制引入的。TCP 使用序列号来标识数据的顺序,数据必须按照顺序处理,如果前面的数据丢失,后面的数据就算到达了也不会通知应用层来处理。 因为 HTTP/2.0 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。由于多个数据流使用同一个 TCP 连接,遵守同一个流量状态控制和拥塞控制。一旦发生丢包的情况,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须要去等待这个丢了的包被重传回来。所以当丢包率高的时候,HTTP/2.0 的表现甚至不如 HTTP/1.1。HTTP/2.0 出现的这个问题是由于其使用 TCP 协议的问题,与它本身的实现其实并没有多大关系。
HTTP/3.0
特性
- Quick UDP Internet Connection
- 基于 UDP 实现了类似 TCP 的流量控制、可靠传输机制
- 集成了 TLS
- HTTPS 要建立连接的话,要花费 6 次交互,先是要建立三次握手,然后是 TLS 的三次握手。QUIC 直接把之前的 TCP 的三次握手和 TLS 的三次握手合并为了一共 3 次,减少了交互的次数
- 头部压缩算法使用了 QPACK
- 使用了 HTTP 2 的多路复用,再加上使用了 UDP,真正解决了队头阻塞问题
- 快速握手,快速启动。因为底层基于 UDP
缺点
- 服务端和客户端对 HTTP 3 的支持还不完善
- 在部署上存在较大难度
HTTPS
HTTP 存在的问题
- 明文传输,具有被窃听的风险,通过抓包工具就可以获取 HTTP 传输过程中的数据
- 传输内容可能被篡改,通过抓包工具可以获取 HTTP 传输的内容进行修改之后,再发送出去
- 存在被冒充的风险,因为冒充者可以收到发送方信息,也就可以冒充发送方给接收方发送信息
HTTPS 如何解决 HTTP 存在的问题
- 信息加密:HTTPS 使用混合加密的方式,解决了窃听风险。对称加密的双方只有一个密钥,加解密用的是同一个密钥,速度较快,但是密钥必须要保密;非对称加密有公钥和私钥,公钥公开,私钥自己保存,公钥加密的数据只能用私钥解密,私钥加密的数据只能用公钥解密。但是非对称加密的加解密速度较慢。所以 HTTPS 选择在通讯建立的时候使用非对称加密,正常沟通的时候使用对称加密,同时确保了安全性和性能。
- 校验机制:为了保证传输内容不被篡改,客户端会先根据传输内容计算出一个 hash 值,然后把这个 hash 值和内容一起传输给服务端。服务端收到请求后,也会根据内容计算出一个 hash 值,然后跟对方传过来的 hash 进行一个比对,如果两个 hash 值相同,则说明内容没有被篡改。
- 数字证书:如何确保客户端收到的公钥是服务端发送的,而不是中间人发送的呢?利用权威机构发布的 CA(数字证书认证机构)可以证明服务器的身份,只要证书可信那么公钥就可信。
混合加密的意义
- 公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;
- 私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。
- 一般我们不会用非对称加密来加密实际的传输内容,因为非对称加密的计算比较耗费性能的,所以 HTTPS 中用的就是上面所说的私钥加密,公钥解密的方式
TLS 握手
- ClientHello:首先客户端向服务端发起加密通信请求。请求包含了 SSL/TLS 的协议版本、客户端生成的一个随机数 client_random(用于后续生成会话密钥)、客户端支持的加密算法(比如 RSA 加密算法)
- ServerHello:服务端收到客户端的请求后,返回给客户端一个请求,内容包含确认的 SSL/TLS 版本以及加密算法、服务端生成的随机数 server_random(用于后续生成会话密钥)、服务器的数字证书
- 客户端响应:客户端收到服务器的响应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器公钥的正确性。确认服务器的公钥没问题之后,客户端生成一串随机字符串 premaster_secret,使用服务器的公钥加密它
- 服务端响应:服务端使用私钥解密上面的随机字符串 premaster_secret
- 生成对称密钥:此时服务端、客户端均拥有了生成密钥的三个要素 client_random、server_random、premaster_secret,可以使用之前协商的加密算法生成对称密钥
- 客户端就绪:客户端发送经过对称密钥加密过的 finished 信号
- 服务端就绪:服务端发送经过对称密钥加密过的 finished 信号
- 握手完成:接下来的会话都通过对称密钥加密
RSA 加密算法
具体加密算法见蛋老师视频
- 公钥:指纹 = 明文^E % N
- 私钥:指纹 = 密文^D % N
数字证书和 CA
数字证书通常包括:
- 公钥
- 持有者信息
- CA 的信息
- 证书有效期
- CA 对文件的数字签名以及使用的算法
CA 就是网络世界中的公安局,具有极高的可信度,所以由它来给各个公钥签名,信任的一方签发的证书,必定也是可信任的。之所以要签名,是因为签名可以避免中间人在获取证书时对证书内容进行篡改。
数字证书的签发和验证流程:
- 签发:首先把持有者的公钥、持有者信息、证书有效期等信息打包成一个包,再对这些信息进行 hash 计算,得到一个 hash 值。然后使用自己的私钥对该 hash 进行加密,生成数字签名,最后把数字签名加入到证书中。
- 验证:客户端会使用同样的 hash 算法获取该证书的 hash 值 H1,然后使用浏览器和操作系统中集成的 CA 公钥来解密数字证书的内容来得到一个 H2,将二者进行比较。如果相同则证明该证书是可信的,如果不相同,则证明是不可信的。
WebSocket
为什么需要 WebSocket
WebSocket 解决了一个 HTTP 的致命问题:请求只能由客户端发起的问题,即使 HTTP/2.0 中新增了服务端推送,但是依然是在客户端发起请求之后才新增的。如果说服务器有连续的状态变化,客户端获知就非常麻烦,只能通过轮询的方法来获取。
特点
- 支持双向通信,实时性更强
- 可以发送文本,也可以发送二进制数据
- 建立在 TCP 之上
- 数据格式轻量,开销小
- 没有同源策略限制
- 与 HTTP 有着很好的兼容性,它的默认端口也是 80(ws)和 443(wss),并且握手阶段使用和 HTTP 一样的方式
DNS
什么是 DNS
一方面 DNS 是一个分层的 DNS 服务器实现的分布式数据库,另一方面,DNS 是一个使得主机能够查询分布式数据库的应用层协议。DNS 端口号一般为 53。
DNS 层次结构
从上到下依次为根域名服务器、顶级域名服务器、权威域名服务器。根域名服务器全球有 13 个。顶级服务器负责所有顶级域名和国家域名(如 uk、jp 等)。比如说对于 www.baidu.com.,最后有一个 .,只不过我们通常省略了 .,这个 . 就是根域名,com 就是顶级域名。 除此之外还要本地 DNS 服务器,一般每个 ISP 都至少有一台本地 DNS 服务器,比如一个居民区的 ISP、一个大学的 ISP、一个机构的 ISP,都有一台或多台本地 DNS 服务器。当主机与某个 ISP 相连,该 ISP 提供一台主机的 IP 地址,该主机具有一台或多台本地 DNS 服务器。主机的本地 DNS 服务器通常和主机距离最近,当主机发起 DNS 请求时,请求会被发送到本地 DNS 服务器,本地 DNS 服务器会把请求转发到 DNS 服务的层次结构。
DNS 记录与报文
每个 DNS 响应报文一般包含多条资源记录,一条资源记录的具体格式为:
(Name,Value,Type,TTL)
其中 TTL 是资源记录的生存时间。Type 的常用值一般有四种,分别是 A、NS、CNAME 和 MX ,不同 Type 的值,对应资源记录代表的意义不同:
- 如果 Type = A(Address),则 Name 是主机名,Value 是主机名对应的 IP 地址。因此一条记录为 A 的资源记录,提供了标准的主机名到 IP 地址的映射
- 如果 Type = NS(Name Server),则 Name 是个域名,Value 是负责该域名的 DNS 服务器的主机名。这个记录主要用于 DNS 链式查询时,返回下一级需要查询的 DNS 服务器的信息
- 如果 Type = CNAME(Canonical Name),则 Name 为别名,Value 为该主机的规范主机名
- 如果 Type = MX(Mail Exchange),则 Name 为一个邮件服务器的别名,Value 为邮件服务器的规范主机名。它的作用和 CNAME 是一样的,都是为了解决规范主机名不利于记忆的缺点
DNS 查询
一般来说 DNS 客户端设置的是递归查询,而其余的查询是迭代查询(如上方右图)。那么为什么要这样呢?主要是为了减轻根域名服务器的压力。从图中显然可以看出,第一种情况下根域名承载的压力过大,而图二中压力可以得到减轻。
DNS 为什么使用 UDP 而不是 TCP
- UDP 不需要建立连接和断开连接的过程,域名解析应该尽可能地快,以防影响网页的加载速度
- 注意问题本身其实并不合理。实际上 DNS 既使用 UDP 也使用 TCP。辅助 DNS 服务器会定时向主 DNS 域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。当发生区域传输的时候,DNS 会使用 TCP,因为需要传输的数据量非常大,UDP 是有边界的,无法传输如此大量的数据。而且,当数据包很大的时候,三次握手的开销占比就很小了,所以这种情况下使用 TCP 合情合理。
高速缓存
为了提高 DNS 查询效率,并减轻根域名服务器的负荷,在域名服务器中广泛使用了高速缓存。高速缓存用来存放最近查询过的域名以及从哪里获得域名信息的记录。
如何提高 DNS 查询效率和正确性
- 在域名服务器中使用高速缓存,存储最近查询过的域名以及从哪里获得域名信息的记录
- 由于域名到 IP 的映射关系并不是永久不变的,为了保持高速缓存中内容的正确性,域名服务器应该为每项缓存设置过期时间
- 在用户的主机(客户端)中也需要高速缓存。很多用户主机在启动的时候就会从本地域名服务器下载域名和 IP 地址的全部数据库,并且只有在缓存中找不到域名的时候才会向域名服务器查询
DNS 劫持
DNS 劫持即域名劫持,是通过将原域名对应的 IP 地址进行替换从而使得用户访问到错误的网站或者使得用户无法正常访问网站的一种攻击方式。
注意区分 DNS 劫持和 HTTP 劫持:
- DNS劫持现象:你输入一个 google.com 网址,出来的是百度的页面
- HTTP劫持现象:访问着 github 的页面,右下角出现了一个格格不入的广告弹窗
DNS 的劫持方法很多,比如说:
- 本机 DNS 劫持 攻击者通过某些手段使用户的计算机感染上木马病毒,或者恶意软件之后,恶意修改本地 DNS 配置,比如修改本地的 DNS 缓存等
- DNS 污染 直接攻击 DNS 服务器,例如对 DNS 服务器进行 DDOS 攻击,可以使 DNS 服务器宕机,出现异常请求,还可以利用某些手段感染 DNS 服务器的缓存,导致返回的是恶意的 IP 地址
前端可以如何加快 DNS 解析
- DNS Prefetch
X-DNS-Prefetch-Control 头控制着浏览器的 DNS 预读取功能。 DNS 预读取是一项使浏览器主动去执行域名解析的功能,其范围包括文档的所有链接,无论是图片的、CSS 的,还是 JavaScript 等其他用户能够点击的 URL。因为预读取会在后台执行,所以 DNS 很可能在链接对应的东西出现之前就已经解析完毕。这能够减少用户点击链接时的延迟。
开启方式有两种:
- 通过在服务器端发送 X-DNS-Prefetch-Control 报头
- 在文档中使用值为 http-equiv 的<meta>
<meta http-equiv="x-dns-prefetch-control" content="off">
也可以对执行的域名进行预读取。
<link rel="dns-prefetch" href="http://www.spreadfirefox.com/">
注意:dns-prefetch 仅对跨域域上的 DNS 查找有效,因此请避免使用它来指向自己的站点或域名。这是因为,当浏览器看到提示时,背后的 IP 已经被解析完成。
- Preconnect
最佳实践:考虑将 dns-prefetch 与 preconnect 配对。尽管 dns-prefetch 仅执行 DNS 查找,但 preconnect 会建立与服务器的连接。如果站点是通过 HTTPS 服务的,则此过程包括 DNS 解析,建立 TCP 连接以及执行 TLS 握手。将两者结合起来可提供进一步减少跨域请求的感知延迟的机会。使用方法为:
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin> <link rel="dns-prefetch" href="https://fonts.gstatic.com/">
其中注意 preconnect 需要添加 crossorigin,否则可能会导致字体资源等加载出错。
URL & URI
- URL,Uniform Resource Identifier,统一资源标识符,可以唯一标记互联网资源
- URI,Uniform Resource Locator,统一资源定位符,也就是地址,它是 URI 的子集
一句话,只要能唯一标识资源的就是 URI,在 URI 的基础上给出其资源的访问方式的就是 URL
为什么 Charles 等抓包工具能抓到你的包
- 其实就是将抓包工具视为中间人,其对于本地而言相当于服务端,而对于真正的服务端而言则相当于客户端
- 抓包工具分别和本地以及服务器都进行 TLS 握手协商
- 这就需要本地能够信任抓包工具提供的证书(也就是需要额外安装一个证书)
CDN
含义
Content Delivery Network,内容分发网络。通过在网络各处放置节点服务器,构成一层智能虚拟网络,CDN 系统能够实时地根据网络流量和各节点的连接和负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上,加快访问速度。目的是使用户可就近取得所需内容,解决网络拥挤的状况,提高用户访问网站的响应速度。
作用
- CDN 使得访问延时大大降低
- CDN 起到了分流作用,减轻了源站的负担
分发内容
网页内容分为动态内容和静态内容。静态内容指的是长期不需要改变的,动态内容指的是经常会改变的。当然即便是静态内容也不是长期保存在 CDN 的。源服务器发送文件给 CDN 的时候可以利用 HTTP 头部的 Cache-Control 来设置缓存情况。
分发流程
- CDN 没有网站的源内容,因此源服务器会提前把 CDN 的内容备份给服务器,也叫做 push。那么当用户访问的时候,就近的 CDN 就会把静态内容提供给用户。如果源服务器没有提前把静态内容提供给 CDN,那么当用户访问 CDN 的时候,CDN 就需要去找源服务器索取对应的静态内容,也叫做 pull。
- 静态内容很容易由源服务器向 CDN 推送,比如图片、字体图标等。但是动态内容,源服务器就无法向 CDN 推送了,比如视频的点赞数,源服务器不可能提前知道点赞数是多少,也就不可能提前把资源推送给 CDN。那么如果等用户索取的时候 CDN 再去问源服务器索取内容,这样 CDN 就提供不了加速服务,也就不存在意义了。所以有些 CDN 会提供可以运行在 CDN 的接口,让源服务器使用这些接口。这样就可以从 CDN 的接口中获取数据,而不需要从源服务器获取了。
安全性
CDN 的存在使得 DDOS 攻击无法对源服务器施行,但是攻击依然可以对 CDN 服务器进行。如果 CDN 宕机了又怎么办呢?实际上,CDN 服务的供应商会监控 CDN 服务器的负载情况,如果某台服务器超载了,就会把用户请求转移到其他没有超负载的服务器上,也就是负载均衡。
工作流程
- 用户访问一个网站,向本地 DNS 服务器请求该域名对应的 IP 地址
- 由于是第一次访问,本地 DNS 服务器也没有缓存记录,于是发起查询查询
- 查询最终返回的结果是指向该网站的权威域名服务器,于是本地 DNS 服务器向该权威域名服务器请求该域名所对应的 IP 地址,这种权威域名服务器通常是 CDN 专用的
- 权威域名服务器根据自己本地配置的负载均衡策略,返回一台 CDN 服务器的 IP 地址给本地 DNS 服务器
- 本地 DNS 服务器拿到 IP 地址后返回给用户
- 用户根据本地 DNS 服务器返回的 IP 对真实服务器进行访问
- 服务器返回响应