1. HTTP 头部包含哪些信息 ★★★
HTTP 头部本质上是一个传递额外重要信息的键值对
HTTP 头部主要分为:通用头部、请求头部、响应头部、实体头部
通用头部
协议头 说明 举例 Cache-Control 用来指定当前的请求/回复中是否使用缓存机制 Cache-Control: no-store Connection 客户端(浏览器)想要优先使用的连接类型 Connection: keep-alive(Upgrade) Date 报文创建时间 Date: Dec, 26 Dec 2024 18:18:00 GMT Trailer 会实现说明在报文主体后记录哪些首部字段,该首部字段可以使用在 HTTP 1.1 版本分块传输编码时 Trailer: Expiress Transfer-Encoding 用来改变报文格式 Transfer-Encoding: chunked Upgrade 要求服务器升级到一个高版本协议 Upgrade: HTTP 2.0, SHTTP 1.3, IRC 6.9, RTA x11 Via 告诉服务器,这个请求是由哪些代理发出的 Via: 1.0 fred, 1.1 itbilu.com.com(Apache 1.1) Warning 一个一般性的警告,表示在实体内容中可能存在错误 Warning: 199 Miscellaneous warning 请求头部
协议头 说明 举例 Accept 告诉服务器自己允许哪些媒体类型 Accept: text/plain Accept-Charset 浏览器声明可接受的字符集 Accept-Charset: uft-8 Accept-Encoding 浏览器声明可接受的编码方法 Accept-Encoding: gzip, deflate Accept-Language 浏览器可接受的响应内容语言列表 Accept-Language: en-US Authorization 用于表示 HTTP 协议中需要认证资源的认证信息 Authorization: Basic OSdjJGRpbjpvcGVul ANIc2SdDE== Expect 表示客户端要求服务器做出特定的行为 Except: 100-continue From 发起此请求的用户的邮件地址 From: user@itbilu.com Host 表示服务器的域名以及服务器所监听的端口号 Host: www.itbilu.com:80 If-XXX 条件请求 If-Modified-Since: Dec, 26 Dec 2024 16:18:00 GMT Max-Forwards 限制该消息可被代理及网关转发的次数 Max-Forwards: 10 Range 表示请求某个实体的一部分,字节偏移以 0 开始 Range: bytes=500-999 Referer 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面 Referer: http://itbilu.com/nodejs User-Agent 浏览器的身份标识字符串 User-Agent: Mozilla/… 响应头部
协议头 说明 举例 Accept-Ranges 字段的值表示可用于定义范围的单位 Accept-Ranges: bytes Age 创建响应的时间 Age: 5733447 ETag 唯一标识分配的资源 Etag: W/‘’585cd998-7c0f’’ Location 表示重定向后的 URL Location: https://kmxz.net/ Retry-After 告知客户端多久后再发送请求 Retry-After: 120 Server 告知客户端服务器信息 Server: Apache 1.3.27 (Unix)(Red-Hat/Linux) Vary 缓存控制 Vary: Origin 实体头部
协议头 说明 举例 Allow 对某网络资源的有效的请求行为,不允许则返回 405 Allow: GET, HEAD Content-encoding 返回内容的编码方式 Content-Encoding: gzip Content-Length 返回内容的字节长度 Content-Length: 348 Content-Language 响应体的语言 Content-Language: en, zh Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.html Content-MD5 返回资源的 MD5 校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022 Content-Type 返回内容的 MIME 内容 Content-Type: text/html; charset-utf-8 Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2024 16:00:00 GMT Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2024 12:45:26 GMT
2. Keep-Alive vs 非 Keep-Alive 的区别以及对服务器性能的影响 ★★★
- 在早期的 HTTP 1.0 中,浏览器每次发起 HTTP 请求都要与服务器创建一个新的 TCP 连接,服务器完成请求处理后立即断开 TCP 连接,服务器不跟踪每个客户也不记录过去的请求。然而创建和关闭连接的过程需要消耗资源和时间,为了减少资源消耗、缩短响应时间,就需要重用连接。在 HTTP 1.1 版本中默认使用持久连接,在此之前的 HTTP 版本的默认连接都是使用非持久连接,如果想要在旧版本的 HTTP 协议上维持持久连接,则需要指定 connection 的首部字段的值为 Keep-Alive 来告诉对方这个请求响应完成后不要关闭,下一次还用这个请求继续交流。用一个示意图来更加生动得表示两者的区别:
对于非 Keep-Alive 来说,必须为每一个请求的对象建立和维护一个全新的连接。对于每一个这样的连接,客户机和服务器都要分配 TCP 的缓冲区和变量,这给服务器带来严重的负担,因为一台 Web 服务器可能同时服务于数以百计的客户机请求。在 Keep-Alive 方式下,服务器在响应后保持该 TCP 连接打开,在同一个客户机与服务器之间的后续请求和响应报文可通过相同的连接进行传送。甚至位于同一台服务器的多个 Web 页面在从该服务器发送给同一个客户机时,可以在单个持久 TCP 连接上进行
然而,Keep-Alive 并不是没有缺点的,当长时间的保持 TCP 连接时容易导致系统资源被无效占用,若对 Keep-Alive 模式配置不当,将有可能比非 Keep-Alive 模式带来的损失更大。因此,我们需要正确地设置 Keep-Alive timeout 参数,当 TCP 连接在传送完最后一个 HTTP 响应,该连接会保持 keepalive_timeout 秒,之后就开始关闭这个连接
3. HTTP 长连接短连接的使用场景 ★★★
- 长连接:多用于操作频繁、点对点(P2P)的通讯,而且客户端连接数目较少的情况。例如即时通讯、网络游戏等
- 短连接:用户数目较多的 Web 网站的 HTTP 服务一般用短连接。例如京东、淘宝这样的大型网站一般客户端数量达到千万级甚至上亿,若采用长连接势必会使得服务端大量的资源被无效占用,所以一般使用的是短连接
4. 怎么知道 HTTP 的报文长度 ★★
当响应消息中存在 Content-Length 字段时,我们可以直接根据这个值来判断数据是否接收完成。例如客户端向服务器请求一个静态页面或者一张图片时,服务器能够很清楚地知道请求内容的大小,因此可以通过消息首部字段 Content-Length 来告诉客户端需要接收多少数据,但是如果服务器预先不知道请求内容的大小,例如加载动态页面的时候,就需要使用 Transfer-Encoding: chunked 的方式来代替 Content-Length
分块传输编码(Chunked transfer encoding)是 HTTP 1.1 中引入的一种数据传输机制,其允许 HTTP 由服务器发送给客户端的数据可以分成多个部分。当数据分解成一系列数据块发送时,服务器就可以发送数据而不需要预先知道发送内容的总大小,每一个分块包含十六进制的长度值和数值,最后一个分块长度值为 0,表示实体结束,客户机可以以此为标志确认数据已经接收完毕
5. HTTP 方法有哪些 ★★★
HTTP 1.0 定义了三种请求方法:GET, POST 和 HEAD 方法
HTTP 1.1 增加了六种请求方法:OPTIONS, PUT, PATCH, DELETE, TRACE 和 CONNECT 方法
方法 描述 GET 请求指定的页面信息,并返回具体内容,通常只用于读取数据 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 POST 向指定资源提交数据进行处理请求(例如提交表单或上传文件)。数据被包含在请求体中,POST 请求可能会导致新的资源的建立或已有资源的更改 PUT 替换指定的资源,没有的话就新增 DELETE 请求服务器删除 URL 标识的资源数据 CONNECT 将服务器作为代理,让服务器代替用户进行访问 OPTIONS 向服务器发送该方法,会返回对指定资源所支持的 HTTP 请求方法 TRACE 回显服务器收到的请求数据,即服务器返回自己收到的数据,主要用于测试和诊断 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新
6. GET 和 POST 的区别 ★★★★★
- GET 提交的数据会放在 URL 之后,并且请求参数会被完整地保留在浏览器的记录里。由于参数直接暴露在 URL 中,可能会存在安全问题,因此往往用于获取资源信息。而 POST 参数放在请求主体中,并且参数不会被保留,相比 GET 方法,POST 方法更安全,主要用于修改服务器上的资源
- GET 请求只支持 URL 编码,POST 请求支持多种编码格式
- GET 只支持 ASCII 字符格式的参数,而 POST 方法没有限制
- GET 提交的数据大小有限制(这里所说的限制是针对浏览器而言的),而 POST 方法提交的数据没限制
- GET 方式需要使用 Request.QueryString 来取得变量的值,而 POST 方式通过 Request.Form 来获取
- GET 方法产生一个 TCP 数据包,POST 方法产生两个(并不是所有的浏览器中都产生两个)
7. GET 和 POST 的长度限制 ★★★
HTTP 中 GET 方法是通过 URL 传递数据的,而 URL 本身并没有对数据的长度进行限制,真正限制 GET 长度的是浏览器。例如 IE 浏览器对 URL 的最大限制为 2000 多个字符,大概 2 KB 左右;像 Chrome、FireFox 等浏览器能支持的 URL 字符数更多,其中 FireFox 中 URL 最大长度限制为 65536 个字符、Chrome 浏览器中 URL 最大长度限制为 8182 个字符。并且这个长度不是只针对数据部分,而是针对整个 URL 而言,在这之中,不同的服务器同样影响 URL 的最大长度限制。因此对于特定的浏览器,GET 的长度限制不同
由于 POST 方法请求参数在请求主体中,理论上讲,POST 方法是没有大小限制的,而真正其限制作用的是服务器处理程序的处理能力
8. HTTP 和 HTTPS 的工作方式(建立连接的过程) ★★★★
HTTP
- HTTP(Hyper Text Transfer Protocol: 超文本传输协议)是一种简单的请求-响应协议,被用于在 Web 浏览器和网站服务器之间传递消息
- HTTP 使用 TCP(而不是 UDP)作为它的支撑运输层协议。其默认工作在 TCP 协议 80 端口,HTTP 客户机发起一个与服务器的 TCP 连接,一旦连接建立浏览器和服务器进程就可以通过套接字接口访问 TCP
- 客户机从套接字接口发送 HTTP 请求报文和接收 HTTP 响应报文。类似的,服务器也是从套接字接口接收 HTTP 请求报文和发送 HTTP 响应报文
- 其通信内容以明文的方式发送,不通过任何方式的数据加密。当通信结束时,客户端与服务端关闭连接
HTTPS
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer) 是以安全为目标的 HTTP 协议,在 HTTP 的基础上通过传输加密和身份认证的方式保证了传输过程的安全性。其工作流程如下:
- 客户端发起一个 HTTPS 请求,并连接到服务器的 443 端口,发送的信息主要包括自身所支持的算法列表和密钥长度等
- 服务端将自身支持的所有加密算法与客户端的算法列表进行对比并选择一种支持的加密算法,然后将它和其他秘钥组件一同发送给客户端
- 服务器向客户端发送一个包含数字证书的报文,该数字证书中包含证书的颁发机构、过期时间、服务端的公钥等信息
- 最后服务端发送一个完成报文通知客户端 SSL 的第一阶段以及协商完成
- SSL 第一次协商完成后,客户端发送一个回应报文,报文中包含一个客户端生成的随机密码串,称为 pre_master_secre,并且该报文是经过证书中的公钥加密过的
- 紧接着客户端会发送一个报文提示服务端在此之后的报文是采用 pre_master_secre 加密的
- 客户端向服务端发送一个 finish 报文,这次握手中包含第一次握手至今所有报文的整体校验值,最终协商是否完成取决于服务端能否成功解密
- 服务端同样发送与第 6 步中相同作用的报文,以让客户端进行确认,最后发送 finish 报文告诉客户端自己能够正确解密报文
当服务端和客户端的 finish 报文交换完成之后,SSL 连接就算建立完成了,之后就进行和 HTTP 相同的通信过程
唯一不同的是在 HTTP 通信过程中并不是采用明文传输,而是采用对称加密的方式,其中对称秘钥已经在 SSL 的建立过程中协商好了
9. HTTP 和 HTTPS 的区别 ★★★★
- HTTP 协议以明文方式发送内容,数据都是未加密的,安全性较差。HTTPS 数据传输过程是加密的,安全性较好
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80 端口,后者是 443 端口
- HTTPS 协议需要用到数字认证机构(Certificate Authority, CA)申请证书,一般需要一定的费用
- HTTP 页面响应比 HTTPS 快,主要因为 HTTP 使用 3 此握手建立连接,而 HTTPS 除了 TCP 的 3 次握手,还需要经历一个 SSL 协商过程
10. HTTPS 的加密方式 ★★★
- HTTPS 采用对称加密和非对称加密组合的方式,首先使用 SSL/TLS 协议进行加密传输
- 为了弥补非对称加密的缺点,HTTPS 采用证书来进一步加强非对称加密的安全性
- 通过非对称加密,客户端和服务端协商好之后进行通信传输的对称密钥
- 后续的所有信息都通过该对称密钥进行加密解密,完成整个 HTTPS 的流程
11. 客户端为什么信任第三方证书 ★★
假设中间人篡改了证书原文,由于他没有 CA 机构的私钥,所以无法得到此时加密后的签名,因此无法篡改签名。客户端浏览器收到该证书后会发现原文和签名解密后的值不一样,则说明证书被中间人篡改,证书不可信,从而终止向服务器传输信息
上述过程说明证书无法被篡改,我们考虑更严重的情况。例如中间人拿到了 CA 机构认证的证书,它想窃取网站 A 发送给客户端的信息,于是它成为中间人拦截到了 A 传给客户端的证书,然后将其替换为自己的证书。此时客户端浏览器收到的是被中间人掉包后的证书,但由于证书里包含了客户端请求的网站信息,因此客户端浏览器只需要把证书里的域名与自己请求的域名对比一下就知道证书有没有被掉包了
12. HTTP 是不保存状态的协议,如何保存用户状态 ★★★★
我们知道,假如某个特定的客户机在短时间内两次请求同一个对象,服务器并不会因为刚刚为该用户提供了对象就不再做出反应,而是重新发送该对象,就像该服务器已经完全忘记不久之前所做过的一样。因为一个 HTTP 服务器并不保存关于客户机的任何信息,所以我们说 HTTP 是一个无状态协议
通常有两种解决方案:
基于 Session 实现的会话保持
- 方案:在客户端第一次向服务端发送 HTTP 请求后,服务器会创建一个 Sesseion 对象并将客户端的身份信息以键值对的形式存储下来,然后分配一个会话标识(SesseionId)给客户端,这个会话标识一般保存在客户端 Cookie 中,之后每次浏览器发送 HTTP 请求都会带上 Cookie 中的 SessionId 到服务器,服务器根据会话标识就可以将之前的状态信息与会话联系起来,从而实现会话保持
- 优点:安全性高,因为状态信息保存在服务器端
- 缺点:由于大型网站往往采用的是分布式服务器,浏览器发送的 HTTP 请求一般要先通过负载均衡器才能到达具体的后台服务器,如果同一个浏览器两次 HTTP 请求分别落在不同的服务器上时,基于 Session 的方法就不能实现会话保持了
- 解决方法:采用中间件,例如 Redis,我们通过将 Session 的信息存储在 Redis 中,使得每个服务器都可以访问到之前的状态信息
基于 Cookie 实现的会话保持
- 方案:当服务器发送响应消息时,在 HTTP 响应头中设置 Set-Cookie 字段,用来存储客户端的状态信息。客户端解析出 HTTP 响应头中的字段信息,并根据其生命周期创建不同的 Cookie,这样一来每次浏览器发送 HTTP 请求的时候都会带上 Cookie 字段,从而实现状态保持。基于 Cookie 的会话保持与基于 Session 的会话保持最主要的区别是前者将会话状态信息存储在浏览器 Cookie 中
- 优点:服务器不用保存状态信息,减轻服务器存储压力,同时便于服务器做水平拓展
- 缺点:该方式不够安全,因为状态信息存储在客户端,这意味着不能在会话中保存机密数据。除此之外,浏览器每次发起 HTTP 请求时都需要发送额外的 Cookie 到服务器端,会占用更多带宽
- 拓展:如果遇到 Cookie 被禁用的情况,则可以通过重写 URL 的方式将会话标识放在 URL 的参数里,也可以实现会话保持
13. 状态码概述 ★★★★
HTTP 状态码由三个十进制数字组成,第一个数字定义了状态码的类型,后两个并没有起到分类的作用。HTTP 状态码共有 5 种类型:
分类 分类描述 1XX 指示信息–表示请求正在处理 2XX 成功–表示请求已被成功处理 3XX 重定向–要完成的请求需要进行附加操作 4XX 客户端错误–请求有语法错误或者请求无法实现,服务器无法处理请求 5XX 服务器端错误–服务器处理请求出现错误 相应的 HTTP 状态码列表:
状态码 英文名称 中文描述 100 Continue 继续。客户端继续处理请求 101 Switching Protocol 切换协议。服务器根据客户端的请求切换到更高级的协议 200 OK 请求成功。请求所希望的响应头或数据体将随此响应返回 201 Created 请求已实现。并且有一个新的资源以及依据需求而建立 202 Accepted 请求已接受。已经接受请求,但还未处理完成 203 Non-Authoritative Information 非授权信息。请求成功,但返回的 meta 信息不在原始的服务器中,而是一个副本 204 No Content 无内容。服务器成功处理了请求,但不需要返回任何实体内容 205 Reset Content 重置内容。与 204 类似,不同点是返回此状态码的响应要求请求者重置文档视图 206 Partial Content 部分内容。服务器成功处理了部分 GET 请求 300 Multiple Choices 多种选择。被请求的资源有一系列可供选择的回馈信息,用户或者浏览器能够自行选择一个首选地址进行重定向 301 Moved Permanently 永久移动。请求的资源已被永久地移动到新 URI,返回信息会包含新的 URI,浏览器会自动定向到新 URI 302 Found 临时移动。与 301 类似,但资源只是临时被移动,客户端应继续使用原有 URI 303 See Other 查看其它地址。与 301 类似,使用 GET 和 POST 查看请求 304 Not Modified 未修改。如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码 305 Use Proxy 使用代理。被请求的资源必须通过指定的代理才能被访问 306 Unused 在最新版的规范中,306 状态码已经不再被使用 307 Temporary Redirect 临时重定向。请求的资源现在临时从不同的 URI 响应请求,与 302 类似 400 Bad Request 客户端请求的语法错误,服务器无法理解;请求的参数有误 401 Unauthorized 当前请求需要用户验证 402 Payment Required 该状态码是为了将来可能的需求而预留的 403 Forbidden 服务器已经理解请求,但是拒绝执行它 404 Not Found 请求失败,请求所希望得到的资源未在服务器上发现 405 Method Not Allowed 客户端请求中的方法被禁止 406 Not Acceptable 请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体 407 Proxy Authentication Required 与 401 响应类似,只不过客户端必须在代理服务器中进行身份验证 408 Request Time-Out 请求超时。服务器等待客户端发送的请求时间过长而超时 409 Conflict 由于和被请求的资源的当前状态之间存在冲突,请求无法完成 410 Gone 被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址 411 Length Required 服务器拒绝在没有定义 Content-Length 头的情况下接受请求 412 Precondition Failed 客户端请求信息的先决条件错误 413 Request Entity Too Large 服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围 414 Request-URI Too Large 请求的 URI 长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务 415 Unsupported Media Type 服务器无法处理请求附带的媒体格式 416 Requested range not satisfiable 客户端请求的范围无效 417 Expectation Failed 服务器无法满足 Expect 的请求头信息 500 Internal Server 服务器遇到了一个未曾预料的状况,导致了她无法完成对请求的处理 501 Not Implemented 服务器不支持当前请求所需要的某个功能 502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到无效的响应 503 Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求,一段时间后可能恢复正常 504 Gateway Time-Out 充当网关或者代理的服务器,未及时从远端服务器获取请求 505 HTTP Version not supported 服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本
14. HTTP 1.0 和 HTTP 1.1 的区别 ★★★
- 缓存处理:在 HTTP 1.0 中主要使用 header 里的 if-modified-Since, Expries 来做缓存判断的标准;而 HTTP 1.1 请求头中添加了更多与缓存相关的字段,从而支持更为灵活的缓存策略。例如 Entity-tag, If-Unmodified-Since, If-Match, If-None-Match 等可供选择的缓存头来控制缓存策略
- 节约带宽:当客户端请求某个资源时,HTTP 1.0 默认将该资源相关的整个对象传送给对方,但很多时候可能客户端并不需要对象的所有信息;而在 HTTP 1.1 的请求头中引入了 range 头域,它允许只请求部分资源,其使得开发者可以多线程请求某一资源,从而充分地利用带宽资源,实现高效并发
- 错误通知的管理:HTTP 1.1 在 1.0 的基础上新增了 24 个错误状态响应码,例如 414 表示客户端请求中所包含的 URL 地址太长,以至于服务器无法处理;410 表示所请求的资源已经被永久删除
- Host 请求头:早期 HTTP 1.0 中认为每台服务器都绑定一个唯一的 IP 地址并提供单一的服务,请求消息的 URL 中并没有传递主机名。而随着虚拟主机的出现,一台物理服务器上可以存在多个虚拟主机,并且他们共享同一个 IP 地址。为了支持虚拟主机,HTTP 1.1 中添加了 host 请求头,请求消息和响应消息中应声明这个字段,若请求消息中缺少该字段服务端会响应一个 404 错误状态码
- 长连接:HTTP 1.0 默认浏览器和服务器之间保持短暂连接,浏览器的每次请求都需要与服务器建立一个 TCP 连接,服务器完成后立即断开 TCP 连接。HTTP 1.1 默认使用的是持久连接,其支持在同一个 TCP 请求中传送多个 HTTP 请求和响应。在此之前的 HTTP 版本的默认连接都是使用非持久连接,如果想要在就版本的 HTTP 协议上维持持久连接,则需要指定 Connection 的首部字段的值为 Keep-Alive
15. HTTP 1.x 和 HTTP 2.0 的区别 ★★★
- 相比于 HTTP 1.X 的文本(字符串)传送,HTTP 2.0 采用二进制传送。客户端和服务端传输数据时把数据分成帧,帧组成了数据流,流具有流 ID 标识和优先级,通过优先级以及流依赖能够一定程度上解决关键请求被阻塞的问题
- HTTP 2.0 支持多路复用。因为流 ID 的存在,通过同一个 HTTP 请求可以实现多个 HTTP 请求传输,客户端和服务器可以通过流 ID 来标识究竟是哪个流从而定位到是哪个 HTTP 请求
- HTTP 2.0 头部压缩。HTTP 2.0 通过 gzip 和 compress 压缩头部然后再发送,同时通信双方会维护一张头信息表,所有字段都记录在这张表中,在每次 HTTP 传输时只需要传头字段在表中的索引即可,大大减少了重传次数和数据量
- HTTP 2.0 支持服务器推送。服务器在客户端未经请求许可的情况下,可预先向客户端推送需要的内容,客户端在退出服务时可通过发送复位相关的请求来取消服务端的推送
16. HTTP 3.0 概述 ★★
HTTP 2.0 存在的问题
- 我们知道,传统 Web 平台的数据传输都基于 TCP 协议,而 TCP 协议在创建连接之前不可避免的需要三次握手,如果需要提高数据交互的安全性,即增加传输层安全协议(TLS),还会增加更多的握手次数
- HTTP 从 1.0 到 2.0,其传输层都是基于 TCP 协议的。即使是带来巨大性能提升的 HTTP 2.0,也无法完全解决 TCP 协议存在的固有问题(慢启动、拥塞窗口尺寸的设置等)
- HTTP 2.0 多路复用只是减少了连接数,其队头的拥塞问题并没有完全解决,倘若 TCP 丢包率过大,则 HTTP 2.0 的表现将不如 HTTP 1.1
QUIC 协议
- QUIC(Quick UDP Internet Connections),直译为快速 UDP 网络连接,是 Google 定制的一种基于 UDP 的低延迟传输协议。其主要目的是解决采用传输层 TCP 协议存在的问题,同时满足传输层和应用层对多连接、低延迟等的需求
- 该协议融合了 TCP, TLS, HTTP 2.0 等协议的特性,并基于 UDP 传输,该协议带来的主要提升有:
- 低延迟连接。当客户端第一次连接服务器时,QUIC 只需要 1 RTT(Round-Trid Time) 延迟就可以建立安全可靠的连接(采用 TLS 1.3 版本),相比于 TCP + TLS 的 3 次 RTT 要更加快捷。之后,客户端可以在本地缓存加密的认证信息,当再次与服务器建立连接时可以实现 0 RTT 的连接建立延迟
- QUIC 复用了 HTTP 2.0 协议的多路复用功能,由于 QUIC 基于 UDP,所以也避免了 HTTP 2.0 存在的队头阻塞问题
- 基于 UDP 协议的 QUIC 运行在用户域而不是系统内核,这使得 QUIC 可以快速地更新和部署,从而很好地解决了 TCP 协议部署及更新的困难
- QUIC 的报文是经过加密和认证的,除了少量的报文,其它所有的 QUIC 报文头部都经过了认证,报文主体经过了加密。主要由攻击者篡改了 QUIC 报文,接收端都能及时发现
- 具有前向纠错机制,每个数据报携带了除了本身内容外的部分其它数据报的内容,使得在出现少量丢包的情况下,尽量减少其它包的重传次数,其通过牺牲单个包所携带的有效数据大小换来更少的重传次数,这在丢包数量较小的场景下能够带来一定程度的性能提升
HTTP 3.0 特点
- HTTP 3.0 是在 QUIC 基础上发展起来的,其底层使用 UDP 进行数据传输,上层仍然使用 HTTP 2.0
- 在 UDP 与 HTTP 2.0 之间存在一个 QUIC 层,其中 TLS 加密过程在该层进行处理
- HTTP 3.0 主要有以下几个特点:
- 使用 UDP 作为传输层进行通信
- 在 UDP 之上的 QUIC 协议保证了 HTTP 3.0 的安全性,QUIC 在建立连接的过程中就完成了 TLS 加密握手
- 建立连接快,正常值需要 1 RTT 即可建立连接。如果有缓存之前的会话信息,则直接验证和建立连接,此过程 0 RTT。建立连接时,也可以带有少量业务数据
- 不和具体底层连接绑定,QUIC 为每个连接的两端分别分配了一个唯一的 ID,上层连接只认这对逻辑 ID。网络切换或者断连时,只需要继续发送数据包即可完成连接的建立
- 使用 QPACK 进行头部压缩,因为在 HTTP 2.0 中的 HPACK 要求传输过程有序,这会导致队头阻塞,而 QPACK 不存在这个问题
HTTP 协议的发展变化
17. DNS 的作用和原理 ★★★★
DNS 概念
- DNS(Domain Name System) 是域名系统的英文缩写
- 是一种组织成域层次结构的计算机和网络服务命名系统,用于 TCP/IP 网络
DNS 作用
- 通常我们有两种方式识别主机:通过主机名或者 IP 地址。人们喜欢便于记忆的主机名表示,而路由器则喜欢定长的、有着层次结构的 IP 地址
- 为了满足这些不同的偏好,我们就需要一种能够进行主机名到 IP 地址转换的目录服务,域名系统作为将域名和 IP 地址互相映射的一个分布式数据库,能够使人更方便地访问互联网
DNS 域名解析原理
DNS 采用了分布式的设计方案,其域名空间采用一种树形的层次结构,下图展示了 DNS 服务器的部分层次结构,从上到下依次为根域名服务器、顶级域名服务器和权威域名服务器。其实根域名服务器在因特网上有 13 个,大部分位于北美洲。第二层为顶级域名服务器,这些服务器负责顶级域名(如 com、org、net、edu)和所有国家的顶级域名(如 uk、fr、ca 和 jp)。第三层为权威 DNS 服务器,因特网上具有公共可访问主机(例如 Web 服务器和邮件服务器)的每个组织机构必须提供公共可访问的 DNS 记录,这些记录由组织机构的权威 DNS 服务器负责保存,这些记录将这些主机的名称映射为 IP 地址
除此之外,还有一类重要的 DNS 服务器,叫做本地 DNS 服务器。本地 DNS 服务器严格来说不在 DNS 服务器的层次结构中,但它对 DNS 层次结构是很重要的。一般来说,每个网络服务提供商(ISP)都有一台本地 DNS 服务器。当主机与某个 ISP 相连时,该 ISP 提供一台主机的 IP 地址,该主机具有一台或多台其本地 DNS 服务器的 IP 地址。主机的本地 DNS 服务器通常和主机距离较近,当主机发起 DNS 请求时,该请求被发送到本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 服务器层次结构中
举例,假设主机 A(IP 地址为 abc.xyz.edu)想知道主机 B 的 IP 地址(def.mn.edu),如下图所示,主机 A 首先向它的本地 DNS 服务器发送一个 DNS 查询报文。该查询报文含有被转换的主机名 def.mn.edu。本地 DNS 服务器将该报文转发到根 DNS 服务器,根 DNS 服务器注意到查询的 IP 地址前缀为 edu 后向本地 DNS 服务器返回负责 edu 的顶级域名服务器的 IP 地址列表。该本地 DNS 服务器则再次向这些顶级域名服务器发送查询报文。该顶级域名服务器注意到 mn.edu 的前缀,并用权威域名服务器的 IP 地址进行响应。通常情况下,顶级域名服务器并不总是知道每台主机的权威 DNS 服务器的 IP 地址,而只知道中间的某个服务器,该中间 DNS 服务器依次能找到用于相应主机的 IP 地址,我们假设中间经历了权威服务器 ① 和 ②,最后找到了负责 def.mn.edu 的权威 DNS 服务器 ③,之后,本地 DNS 服务器直接向该服务器发送查询报文从而获得主机 B 的 IP 地址。在下图中,IP 地址的查询其实经历了两种查询方式,分别是递归查询和迭代查询
拓展:域名解析查询的两种方式
- 递归查询:如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户端的身份向其他根域名服务器继续发出查询请求报文,即替主机继续查询,而不是让主机自己进行下一步查询,如上图步骤 ① 和 ⑩
- 迭代查询:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉本地服务器下一步应该找哪个域名服务器进行查询,然后让本地服务器进行后续的查询,如上图步骤 ② ~ ⑨
18. DNS 为什么用 UDP ★★★
- DNS 既使用 TCP 又使用 UDP
- 当进行区域传送(主域名服务器向辅助域名服务器传送变化的那部分数据)时会使用 TCP,因为数据同步传送的数据量比一个请求和应答的数据量要多,而 TCP 允许的报文长度更长,因此为了保证数据的正确性,会使用基于可靠连接的 TCP
- 当客户端向 DNS 服务器查询域名(域名解析)的时候,一般返回的内容不会超过 UDP 报文的最大长度,即 512 字节。用 UDP 传输时,不需要经过 TCP 三次握手的过程,从而大大提高了响应速度,但这要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性
19. 怎样实现 DSN 劫持 ★★★
DNS 劫持概念
- DNS 劫持即域名劫持,是通过将原域名对应的 IP 地址进行替换从而使得用户访问到错误的网站或者使得用户无法正常访问网站的一种共计方式。域名劫持往往只能在特定的网络范围内进行,范围外的 DNS 服务器能够返回正常的 IP 地址
- 攻击者可以冒充原域名所属机构,通过电子邮件的方式修改组织机构的域名注册信息,或者将域名转让给其他组织,并将新的域名信息保存在所指定的 DNS 服务器中,从而使得用户无法通过对原域名进行解析来访问目的网址
具体实施步骤
- 获取要劫持的域名信息:攻击者首先会访问域名查询站点查询要劫持的域名信息
- 控制域名相应的 e-mail 账号:在获取到域名信息后,攻击者通过暴力破解或者专门的方法破解公司注册域名时使用的 e-mail 账号所对应的密码。更高级的攻击者甚至能够直接对 e-mail 进行信息窃取
- 修改注册信息:当攻击者破解了 e-mail 之后,会利用相关的更改功能修改该域名的注册信息,包括域名拥有者信息、DNS 服务器信息等
- 使用 e-mail 收发确认函:在修改完注册信息后,攻击者在 e-mail 真正拥有者之前收到修改域名注册信息的相关确认信息,并回复确认修改文件,待网络公司回复已成功修改信件后,攻击者便成功完成 DNS 劫持
用户端的一些预防手段
- 直接通过 IP 地址访问网站,避开 DNS 劫持
- 由于域名劫持往往只能在特定的网络范围内进行,因此一些高级用户可以通过网络设置让 DNS 指向正常的域名服务器以实现对目的网址的正常访问,例如将计算机首选 DNS 服务器的地址固定为 8.8.8.8
20. Socket 套接字有哪些 ★★★
Socket 套接字概念
- Socket 是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象,网络进程通信的一端就是一个套接字,不同主机上的进程便是通过套接字发送报文来进行通信
- 例如 TCP 用主机的 IP 地址 +端口号作为 TCP 连接的端点,这个端点就叫做套接字
Socket 套接字类型
- 流套接字(SOCK_STREAM):流套接字基于 TCP 传输协议,主要用于提供面向连接、可靠的数据传输服务。由于 TCP 协议的特点,使用流套接字进行同行时能够保证数据无差错、无重复传送,并按顺序接收,通信双方不需要在程序中进行相应的处理
- 数据报套接字(SOCK_DGRAM):和流套接字不同,数据报套接字基于 UDP 传输协议,对应于无连接的 UDP 服务应用。该服务并不能保证数据传输的可靠性,也无法保证对端能够顺序接收到数据。此外,通信两端不需建立长时间的连接关系,当 UDP 客户端发送一个数据给服务器后,其可以通过同一个套接字给另一个服务器发送数据。当用 UDP 套接字时,丢包等问题需要在程序中进行处理
- 原始套接字(SOCK_RAW):由于流套接字和数据报套接字只能读取 TCP 和 UDP 协议的数据,当需要传送非传输层数据包(例如 Ping 命令时用的 ICMP 协议数据包)或者遇到操作系统无法处理的数据包时,此时就需要建立原始套接字来发送
21. URI 和 URL 的区别 ★★★
- URL,即统一资源定位符(Uniform Resource Locator),URL 其实就是我们平时上网时输入的网址,它标识一个互联网资源,并指定对其进行操作或获取该资源的方法。例如 https://leetcode-cn.com/problemset/all 这个URL,标识一个特定资源并表示该资源的某种形式是可以通过 HTTP 协议从相应位置获得
- 从定义即可看出,URL 是 URI 的一个子集,两者都定义了资源是什么,而 URL 还定义了如何能访问到该资源。URI 是一种语义上的抽象概念,可以是绝对的、也可以是相对的。而 URL 则必须提供足够的信息来定位,是绝对的。简单地说,只要能唯一标识资源的就是 URI,在 URI 的基础上给出其资源的访问方式的就是 URL
22. 为什么 Fidder、Charles 能抓到你的包(抓取数据包的过程) ★★
抓包原理
- 假如我们需要抓取客户端的数据包,需要监控客户端和服务器交互之间的网络节点,监控其中任意一个网络节点(网卡),获取所有经过网卡中的数据,对这些数据按照网络协议进行解析,这就是抓包的基本原理
- 中间的网络节点不受我们控制,是基本无法实现网络抓包的,因此只能在客户端与服务器之间进行抓包
抓包过程
当抓取 HTTP 数据包时,过程较为简单,这里抓包工具相当于透明人,数据经过的时候它一只手接到数据,然后另一只手把数据传出去
- 首先抓包工具会提出代理服务,客户端需要连接该代理
- 客户端发出 HTTP 请求时,会经过抓包工具的代理,抓包工具将请求的原文进行展示
- 抓包工具使用该原文将请求发送给服务器
- 服务器返回结果给抓包工具,抓包工具将返回结果进行展示
- 抓包工具将服务器返回的结果原样返回给客户端
当抓取 HTTPS 数据包时,这个时候抓包工具对客户端来说相当于服务器,对服务器来说相当于客户端。在这个传输过程中,客户端会以为它就是目标服务器,服务器也会以为它就是请求发起的客户端
- 客户端连接抓包工具提供的代理服务,并安装抓包工具的根证书
- 客户端发出 HTTPS 请求,抓包工具模拟服务器与客户端进行 TLS 握手交换密钥等流程
- 抓包工具发送一个 HTTPS 请求给客户端请求的目标服务器,并与目标服务器进行 TLS 握手交换密钥等流程
- 客户端使用与抓包工具协定好的密钥加密数据后发送给抓包工具
- 抓包工具使用与客户端协定好的密钥解密数据,并将结果进行展示
- 抓包工具将解密后的客户端数据,使用与服务器协定好的密钥进行加密后发送给目标服务器
- 服务器解密数据后,做对应的逻辑处理,然后将返回的结果使用与抓包工具协定好的密钥进行加密发送给抓包工具
- 抓包工具将服务器返回的结果,用与服务器协定好的密钥解密,并将结果进行展示
- 抓包工具将解密后的返回数据,使用与客户端协定好的密钥进行加密后发送给客户端
- 客户端解密数据
23. 如果访问一个网站很慢,怎么排查和解决 ★★★
- 首先最直接的方法是查看本地网络是否正常,可以通过网络测速软件例如电脑管家等对电脑进行测速,若网速正常,我们查看网络带宽是否被占用,例如正在下载电影时并且没有限速,是会影响打开网页的速度的,这种情况往往是处理器内存小导致的
- 当网速测试正常时,我们对网站服务器速度进行排查,通过 ping 命令查看链接到服务器的时间和丢包情况,一个速度好的机房,首先丢包率不能超过 1%,其次 ping 值要小,最后是 ping 值要稳定,如最大和最小差值过大说明路由不稳定。或者我们也可以查看同台服务器上其他网站的的打开速度,看是否其他网站打开也慢
- 如果网页打开的速度时快时慢,甚至有时候打不开,有可能是空间不稳定的原因。当确定是该问题时,就要找你的空间商解决或换空间商了,如果购买空间的话,可选择购买双线空间或多线空间;如果是在有的地方打开速度快,有的地方打开速度慢,那应该是网络线路的问题。电信线路用户访问放在联通服务器的网站,联通线路用户访问放在电信服务器上的网站,相对来说打开速度肯定是比较慢
- 从网站本身找原因。网站的问题主要包括网站程序设计、网页设计结构和网页内容三个部分
- 网站程序设计:当访问网页中有拖慢网站打开速度的代码,会影响网页的打开速度,例如网页中的统计代码,我们最好将其放在网站的末尾。因此我们需要查看网页程序的设计结构是否合理
- 网页设计结构:如果是 table 布局的网站,查看是否嵌套次数太多,或是一个大表格分成多个表格这样的网页布局,此时我们可以采用 div 布局并配合 css 进行优化
- 网页内容:查看网页中是否有许多尺寸大的图片或者尺寸大的 flash 存在,我们可以通过降低图片质量,减小图片尺寸,少用大型 flash 加以解决。此外,有的网页可能过多地引用了其他网站的内容,若某些被引用的网站访问速度慢,或者一些页面已经不存在了,打开的速度也会变慢。一种直接的解决方法是去除不必要的加载项
24. 常见的其他协议 ★
FTP
- FTP(File Transfer Protocol, 文件传输协议) 是用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式,使用 TCP 数据报,提供交互式访问,双向传输
- TFTP(Trivial File Transfer Protocol, 简单文件传输协议) 一个小且易实现的文件传输协议,也使用客户/服务器方式,使用 UDP 数据报,只支持文件传输而不支持交互,没有列目录,不能对用户进行身份鉴定
SMTP
- SMTP(Simple Mail Transfer Protocol, 简单邮件传输协议) 是在 Internet 传输 Email 的标准,是一个相对简单的基于文本的协议
- 在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过 Telnet 程序来测试一个 SMTP 服务器。SMTP 使用 TCP 端口 25
DHCP
- DHCP(Dynamic Host Configuration Protocol, 动态主机设置协议) 是一个局域网的网络协议,使用 UDP 协议工作
- 主要有两个用途:用于内部网络或网络服务供应商自动分配 IP 地址给用户;用于内部网络管理员作为对所有电脑作中央管理的手段
SNMP
- SNMP(Simple Network Management Protocol, 简单网络管理协议) 构成了互联网工程工作小组(IETF, Internet Engineering Task Force)定义的 Internet 协议族的一部分
- 该协议能够支持网络管理系统,用以监测连接到网络上的设备是否有任何引起管理上关注的情况
25. 网页解析全过程(用户输入网址到显示对应页面的全过程)★★★★★
主要阶段分析
- DNS 解析:当用户输入一个网址并按下回车键的时候,浏览器获得一个域名,而在实际通信过程中,我们需要的是一个 IP 地址,因此我们需要先把域名转换成相应的 IP 地址
- TCP 连接:浏览器通过 DNS 获取到 Web 服务器真正的 IP 地址后,便向 Web 服务器发起 TCP 连接请求,通过 TCP 三次握手建立好连接后,浏览器便可以将 HTTP 请求数据发送给服务器了
- 发送 HTTP 请求:浏览器向 Web 服务器发起一个 HTTP 请求,HTTP 协议是建立在 TCP 协议至上的应用层协议,其本质是在建立起的 TCP 连接中,按照 HTTP 协议标准发送一个索要网页的请求。在这一过程中,会涉及到负载均衡等操作
- 处理请求并返回:服务器获取到客户端的 HTTP 请求后,会根据 HTTP 请求中的内容来决定如何获取相应的文件,并将文件发送给浏览器
- 浏览器渲染:浏览器根据响应开始显示页面,首先解析 HTML 文件构成 DOM 树,然后解析 CSS 文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上
- 断开连接:客户端和服务器通过四次挥手终止 TCP 连接
什么是负载均衡
- 负载均衡(Load Balance),其含义是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如 FTP 服务器、Web 服务器、企业核心服务器和其他主要任务服务器等,从而协同完成工作任务。负载均衡建立在现有的网络之上,它提供了一种透明且廉价有效的方法扩展服务器和网络设备的带宽、增加吞吐量、加强网络处理能力并提高网络的灵活性和可用性
- 负载均衡是分布式系统架构设计中必须考虑的因素之一,例如天猫、京东等大型用户网站中为了处理海量用户发起的请求,其往往采用分布式服务器,并通过引入反向代理等方式将用户请求均匀分发到每个服务器上,而这一过程所实现的就是负载均衡
网页解析过程流程图