微信公众号:[前端一锅煮]
一点技术、一点思考。
问题或建议,请公众号留言。
- UDP
- TCP
- 三次握手
- 四次挥手
- 拥塞控制
- HTTP
- HTTP/2
- HTTPS
- 证书认证
- 对称加密
- 非对称加密
- 压缩方式
- 优化网络请求
长篇预警~前端
UDP
UDP(User Data Protocol,用户数据报协议)是一个面向无链接的传输层协议。webpack
- UDP 是一个非链接的协议,传输数据以前源端和终端不创建链接,当它想传送时就简单地去抓取来自应用程序的数据,并尽量快地把它扔到网络上。在发送端,UDP 传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制。在接收端,UDP 把每一个消息段放在队列中,应用程序每次从队列中读一个消息段。
- 因为传输数据不创建链接,所以也就不须要维护链接状态,包括收发状态等,所以一台服务机可同时向多个客户机传输相同的消息。
- UDP 信息包的标题很短,只有 8 个字节,相对于 TCP 的 20 个字节信息包的额外开销很小。
- 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
- UDP 使用尽最大努力交付,即不保证可靠交付,所以主机不须要维持复杂的连接状态表(这里面有许多参数)。
- UDP 是面向报文的。发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付给 IP 层。既不拆分,也不合并,而是保留这些报文的边界,所以,应用程序须要选择合适的报文大小。
TCP
TCP(Transmission Control Protocol,传输控制协议)是一个面向链接的、可靠的、基于字节流的传输层协议。在收发数据前,必须和对方创建可靠的链接。一个 TCP 链接必须通过三次握手才能创建起来,断开链接要通过四次挥手,其中的过程很是复杂。web
三次握手
名词解释:redis
- SYN:表示创建一个链接,携带 SYN 的 tcp 报文段为同步报文段。
- FIN:表示告知对方本端要关闭链接了。
- ACK:表示确认好是否有效,携带 ack 标志的报文段也称确认报文段。只有当 ACK=1 时确认号才有效,当 ACK=0 时确认号无效,这时会要求重传数据,保证数据的完整性。
三次握手过程:算法
- Client:通知 Server 我要链接,不含应用层数据(SYN 1 => Server)。
- Server:收到 Client 通知,赞成链接,不含应用层数据(SYN+ACK 1 => Client)。
- Client:收到了 Server 的赞成(ACK 1 => Server TCP)
注意:数据库
Client:没收到重发,只接受最后一次发 SYN 的 SYN+ACK 回应,忽略其余回应。gulp
Server:没收到重发,一直没收到 ACK,释放资源。浏览器
为何要三次握手:缓存
为了防止无效的链接请求到达服务器。安全
由于有可能客户端先发了一个链接请求报文,可是因为网络的问题,迟迟没有到达服务器。这时候,客户端就超时重传了该报文,而后服务器响应了该请求报文。可是过一会,第一个报文竟然又到了服务器,那么服务器就会把它做为新的链接请求。若是只有两次握手,那么服务器对于该链接请求也会创建链接,但若是是三次握手,服务器发出确认报文后,客户端不予理睬,这样就不会创建TCP链接了。
四次挥手
四次挥手过程:
- Client 我要关闭链接(FIN 1 => Server)
- Server 收到确认,此时 Server 还未关闭(ACK 1 => Client)
- Server 我要关了(FIN 1 => Client)
- Client 收到确认(ACK 1 => Server)
为何要四次挥手
由于服务端在接收到 FIN, 每每不会当即返回 FIN, 必须等到服务端全部的报文都发送完毕了,才能发 FIN。所以先发一个 ACK 表示已经收到客户端的 FIN,延迟一段时间才发 FIN。这就形成了四次挥手。
若是是三次挥手会有什么问题?
等于说服务端将 ACK 和 FIN 的发送合并为一次挥手,这个时候长时间的延迟可能会致使客户端误觉得 FIN 没有到达客户端,从而让客户端不断的重发 FIN。
总结:链接要快,关闭要等。链接不须要等待而要尽可能快,因此第二次握手 SYN+ACK 和到一块儿发送。关闭链接要等,由于数据可能尚未传完,还在路上继续传,因此分开,先告诉客户端已经收到了通知不用再发第二遍了。等数据全传完了再通知客户端我也关闭了。
拥塞控制
tcp 用一系列方法来确保数据的可靠性:去错去重、失序重排、超时重发、应答机制、流量控制、拥塞控制。
- 流量控制:经过接收缓存区的大小,控制发送端的发送。若是对方的接收缓存区满了,就不能再继续发送了。
- 慢启动:拥塞窗口 cwnd 翻倍加大,由小到大根据反馈逐渐增大拥塞窗口。
- 拥塞避免:加大到慢启动阈值的时候,每次加 1。
- 快速重传:若是发生了丢包,即接收端发现数据段不是按序到达的时候,接收端的处理是重复发送以前的 ACK。发送方只要一连收到三个重复确认就应当当即重传对方还没有收到的报文段,而没必要继续等待设置的重传计时器到期。
- 选择性重传:SACK 记录一下哪些包到了,哪些没到,针对性地重传。
- 快速恢复:拥塞阈值下降为 cwnd 的一半,cwnd 的大小变为拥塞阈值,cwnd 线性增长。
HTTP
HTTP 协议,是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP 是一个无状态的协议。无状态是指浏览器和服务器之间不须要创建持久的链接,这意味着当一个客户端向服务器端发出请求,而后服务器返回响应,链接就被关闭了,在服务器端不保留链接的有关信息。
HTTP1.0 最先在网页中使用是在 1996年,使用在一些较为简单的网页上和网络请求上,HTTP1.1 则在 1999年才开始普遍应用于如今的各大浏览器网络请求中,同时 HTTP1.1 也是当前使用最为普遍的 HTTP 协议。主要区别体如今:
- 持久链接:HTTP1.1 支持持久链接,默认开启 Connection: keep-alive,即 TCP 链接默认不关闭,能够被多个请求复用(对于同一个域名,大多数浏览器容许同时创建 6 个持久链接),必定程度上弥补了 HTTP1.0 每次请求都要建立链接的缺点。
- 断点续传:HTTP1.0 不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,容许只请求资源的某个部分,返回码是 206。
- 缓存处理:在 HTTP1.0 中主要使用 header 里的 If-Modified-Since、Expires 来作为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略如 Entity tag、If-Unmodified-Since、If-Match,、If-None-Match 等更多可供选择的缓存头来控制缓存策略。
- 错误通知的管理:HTTP1.1 新增了 24 个错误状态响应码,如 409 表示请求的资源与资源的当前状态发生冲突;410 表示服务器上的某个资源被永久性的删除。
- Host头处理:HTTP1.0 中认为每台服务器都绑定一个惟一的 IP 地址,所以,请求消息中的 URL 并无传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上能够存在多个虚拟主机(Multi-homed Web Servers),而且它们共享一个 IP 地址。HTTP1.1 的请求消息和响应消息都应支持 Host 头域,且请求消息中若是没有 Host 头域会报告一个错误(400 Bad Request)。
缺点:
虽然容许复用 TCP 链接,可是同一个 TCP 链接里面,全部的数据通讯是按次序进行的。服务器只有处理完一个请求,才会接着处理下一个请求。若是前面的处理特别慢,后面就会有许多请求排队等着。这将致使“队头堵塞”。
避免方式:一是减小请求数,二是同时多开持久链接。
HTTP/2
HTTP/2 是 HTTP 协议自 1999 年 HTTP 1.1 发布后的首个更新,主要基于 SPDY 协议,于 2015年5月以 RFC 7540 正式发表。
主要有如下改进:
- 二进制协议:HTTP/1.1 版的头信息确定是文本(ASCII编码),数据体能够是文本,也能够是二进制。HTTP/2 则是一个完全的二进制协议,头信息和数据体都是二进制,而且统称为”帧”:头信息帧和数据帧。二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少。
- 多路复用:HTTP/2 复用 TCP 链接,在一个链接里,客户端和浏览器均可以同时发送多个请求或回应,并且不用按照顺序一一对应,这样就避免了”队头堵塞”。
- 头信息压缩:HTTP 协议是没有状态,致使每次请求都必须附上全部信息。请求的不少头字段都是重复的,好比 Cookie,同样的内容每次请求都必须附带,这会浪费不少带宽,也影响速度。HTTP/2 对这一点作了优化,引入了头信息压缩机制。一方面,头信息使用 gzip 或 compress 压缩后再发送。另外一方面,客户端和服务器同时维护一张头信息表,全部字段都会存入这个表,产生一个索引号,以后就不发送一样字段了,只需发送索引号。这样对于相同的头部,没必要再经过请求发送,只需发送一次。
- 服务器推送:HTTP/2 容许服务器未经请求,主动向客户端发送资源。
HTTPS
HTTP 协议一般承载于 TCP 协议之上,在 HTTP 和 TCP 之间添加一个安全协议层(SSL或TSL),就成了咱们常说的 HTTPS。
HTTPS 主要用到对称加密、非对称加密、证书,等技术进行客户端与服务器的数据加密传输,最终达到保证整个通讯的安全性。
证书认证
服务端证书:SSL 客户端经过 TCP 和服务器创建链接以后(443 端口),而且在通常的 tcp 链接协商(握 手)过程当中请求证书。即客户端发出一个消息给服务器,这个消息里面包含了本身可实现的算法列表和其它一些须要的消息,SSL 的服务器端会回应一个数据包,这里面肯定了此次通讯所须要的算法,而后服务器向客户端返回证书(证书里面包含了域名、申请证书的公司、公共秘钥等信息)。
证书验证:客户端安装了第三方 CA 的根证书,该根证书下的全部证书都将被客户端信任。在收到服务器返回的证书后,使用这个机构的公共秘钥解密签名,获得服务端公钥及其余信息。作数字签名,若是一致,则确认证书合法即服务端被信任。客户端还会确保证书中列出的域名就是它正在链接的域名。
数字签名:第三方认证机构私钥加密给服务器的证书,浏览器获取第三方认证机构公钥解密,客户端利用签名生成规则进行签名生成,看两个签名是否匹配。
数据加密和传输:若是确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。而后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机能够开始进行对称加密进行通讯。
对称加密
对称密钥加密,是指加密和解密使用同一个密钥的方式,加密和解密的算法是公开的,密钥是隐秘的,流行的对称加密算法有:DES、AES。
AES:AES-12八、AES-25六、AES-192。
缺点:
- 密钥分发问题,如何安全的把共享密钥在双方进行分享,这自己也是一个如何安全通讯的问题。一种方法是提早双方约定好,不经过具体的通讯进行协商,避免被监听和截获。另一种方式,将是下面咱们介绍的经过非对称加密信道进行对称密码的分发和共享,即混合加密系统。
- 密钥管理的复杂度问题,对称加密的密钥是一对一的使用方式,若一方要跟n方通讯,则须要维护 n 对密钥。
优势:
- 加密和解密的速度要比非对称加密快不少。
- 密钥 k 的长度越长,对应的密码空间就越大,暴力破解难度越大,就更加安全。
非对称加密
非对称加密,指使用一对非对称密钥,即公钥和私钥,公钥能够随意发布,但私钥只有本身知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用本身的私钥进行解密。
经常使用的非对称加密算法有 RSA:md五、SHA-1,SHA-224,SHA-256,SHA-512,SHA-384。
非对称加密过程:
- 服务端生成配对的公钥和私钥。
- 私钥保存在服务端,公钥发送给客户端。
- 客户端使用公钥加密明文传输给服务端。
- 服务端使用私钥解密密文获得明文。
用公钥加密的密文,只有拥有私钥的一方才能解密,这样加密的各方统一使用一个公钥便可。
优势:不存在密钥分发的问题,解码方能够本身生成密钥对,一个作私钥存起来,另一个做为公钥进行发布。解决了密钥管理的复杂度问题,多个加密方均可以使用一个已知的公钥进行加密,但只有拥有私钥的一方才能解密。
缺点: 加解密的速度没有对称加密快。
四次握手
HTTPS 要通过四次握手创建链接,双方生成会话密钥。
- Client:一个随机数 Client.random。支持的协议版本,好比TLS 1.0版。支持的加密方法,好比 RSA 公钥加密。
- Sever:一个随机数 Server.random。确认使用的加密方法,确认协议。服务器证书:携带服务器证书链,其中有两个证书,第一个是域名的证书,第二个是 CA 证书,用于验证第一个证书的正确性。那如何验证第二个 CA 证书是否被篡改过呢?使用浏览器内置的根证书去验证。
- Client:一个随机数 pre-master,编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送,客户端握手结束通知。
- Sever:编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送,服务器握手结束通知。
四次握手耗时大概是TCP的三倍,保密强度越高的数字证书耗时越长。经历如下过程:
版本+随机数+加密方法;
确认版本+随机数+确认加密方法+服务器证书(服务器证书+中间 CA 证书 根证书);
公钥加密过的随机数+编码改变通知+结束通知;
编码改变通知+结束通知。
这样客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。
session ID
SSL 中的 session 会跟 HTTP 的 session 相似,都是用来保存客户端和服务端之间交互的一些记录。这里的 SSL 的 session 保存的是 SSL 的握手记录。
SSL 握手过程,由于多了几回 RTT,还有加解密的计算,是 HTTPS 的耗时大户,优化的重点。复用了握手记录,能够很显著地提升 HTTPS 的效率。
session ID:服务端保存握手记录,客户端 session ID 会话编号发给服务端验证,只有一台服务器有。
session ticket:客户端保存握手记录,客户端加密的 session ticket 给服务端解密获得上次会话信息,多服务器均可解密获得。
压缩方式
浏览器 Content-Encoding 值:
- gzip:代表实体采用 GUN zip 编码
- compress:代表实体采用 Unix 的文件压缩程序
- deflate:代表实体使用 zlib 的格式压缩
- identity:代表不对实体进行编码,当没有 Content-Encoding 首部的时候,就默认为这种状况
- br:代表实体采用 Brotli 算法编码 一种比 Gzip 压缩率更高的算法,只在 HTTPS 中生效,由于在 HTTP 请求中 request header 里的 Accept-Encoding 是没有 br 这个选项
使用 gzip 压缩文本很是合适,但 png、gif、jpg、jpeg 这类图片文件并不推荐使用 gzip 压缩(svg是个例外),由于通过本地压缩处理后的图片文件 gzip 能压缩的空间很小。事实上,添加标头,压缩字典,并校验响应体可能会让它更大。
优化网络请求
如下是浏览器中一个网络请求的完整过程。
Stalled 检测有没有链接资源
浏览器获得要发出这个请求的指令,到请求能够发出的等待时间。通常是代理协商、以及等待可复用的 TCP 链接释放的时间,不包括 DNS 查询、创建 TCP 链接等时间等。
- 单一服务发送时候 stalled 过长,每每是丢包所致,这也意味着网络或服务端有问题;
- 多个服务并发致使 stalled 过长,是浏览器对同一个主机域名的并发链接数有限制,过长的请求是被阻塞了,处在队列中等待 tcp 链接。
DNS Lookup(域名解析)
在 DNS 查找完成以前,浏览器不能从主机名那里下载到任何东西。
- 利用 DNS 缓存(设置TTL时间);
- 利用 Connection: keep-alive 特性创建持久链接,能够在当前链接上进行多个请求,无需再进行域名解析。
Initial connection(初始化链接)
TCP 创建链接的三次握手时间。
Request sent 请求发完
请求第一个字节发出前到最后一个字节发出后的时间,也就是上传时间。
- 减小 HTTP 请求,可使用 CSS Sprites、内联图片、合并脚本和样式表等;
- 对不常变化的组件添加长久的 Expires 头(至关于设置久远的过时时间),在后续的页面浏览中能够避免没必要要的 HTTP 请求。
Waiting 等待服务器响应
请求发出后,到收到响应的第一个字节所花费的时间。一般是耗费时间最长的。从发送请求到收到响应之间的空隙,会受到线路、服务器距离等因素的影响。
- 经过优化数据库查询条件、数据缓存到 redis 中来加快数据返回速度;
- 使用 CDN,将用户的访问指向距离最近的工做正常的缓存服务器上,由缓存服务器直接响应用户请求,提升响应速度。
Content Download 下载完
收到响应的第一个字节,到接受完最后一个字节的时间,就是下载时间。
- 移除重复脚本,精简和压缩代码,如借助自动化构建工具 webpack、grunt、gulp 等;
- 压缩响应内容,服务器端启用 gzip 压缩,能够减小下载时间。