网络篇:HTTP和TCP介绍

116 阅读9分钟

HTTP 特性

  • 超文本传输协议
  • 简单
    • HTTP 基本的报⽂格式就是 header + body ,头部信息也是 key-value 简单⽂本的形式,易于理解,降低了学习和使⽤的⻔槛。
  • 灵活和易于扩展
    • HTTP协议⾥的各类请求⽅法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发⼈员⾃定义和扩充。同时 HTTP 由于是⼯作在应⽤层(OSI 第七层),则它下层可以随意变化。HTTPS 也就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层,HTTP/3 甚⾄把 TCP 层换成了基于 UDP QUIC。
  • 应⽤⼴泛和跨平台
    • 互联⽹发展⾄今,HTTP 的应⽤范围⾮常的⼴泛,从台式机的浏览器到⼿机上的各种 APP,从看新闻、刷贴吧到购物、理财、吃鸡,HTTP 的应⽤⽚地开花,同时天然具有跨平台的优越性

HTTP 缺点

  • ⽆状态
  • 明⽂传输
  • 同时还有⼀⼤缺点,不安全

HTTP1.1 性能优化

HTTP 协议是基于 TCP/IP,并且使⽤了「请求 - 应答」的通信模式,所以性能的关键就在这两点⾥

  • HTTP/1.1 提出了⻓连接的通信⽅式,也叫持久连接。减少了TCP 连接的᯿复建⽴和断开所造成的额外开销,减轻了服务器端的负载
  • HTTP/1.1 管道⽹络传输。客户端可以发起多个请求,只要第⼀个请求发出去了,不必等其回来,就可以发第⼆个请求出去,可以减少整体的响应时间。但是服务器还是按照顺序,先回应 A 请求,完成后再回应 B 请求。要是前⾯的回应特别慢,后⾯就会有许多请求,排队等着。这称为「队头堵塞」

HTTP1.1缺点

  • 请求 / 响应头部(Header)未经压缩就发送,⾸部信息越多延迟越⼤。只能压缩 Body 的部分;
  • 发送冗⻓的⾸部。每次互相发送相同的⾸部造成的浪费较多;
  • 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端⼀直请求不到数据,也就是队头阻塞;
  • 没有请求优先级控制;
  • 请求只能从客户端开始,服务器只能被动响应

HTTPS 与HTTP的区别

  • 需进⾏ SSL/TLS 的握⼿过程,才可进⼊加密报⽂传输
  • HTTP 的端⼝号是 80,HTTPS 的端⼝号是 443
  • HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的
  • 混合加密的⽅式实现信息的机密性,解决了窃听的⻛险
    • 在通信建⽴前采⽤⾮对称加密的⽅式交换「会话秘钥」,后续就不再使⽤⾮对称加密
    • 在通信过程中全部使⽤对称加密的「会话秘钥」的⽅式加密明⽂数据(对称加密只使⽤⼀个密钥,运算速度快)
  • 摘要算法的⽅式来实现完整性,它能够为数据⽣成独⼀⽆⼆的「指纹」,指纹⽤于校验数据的完整性,解决了篡改的⻛险
  • 将服务器公钥放⼊到数字证书中,解决了冒充的⻛险

HTTP 2.0

HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的

  • 头部压缩。HTTP/2 会压缩头(Header) 如果你同时发出多个请求,他们的头是⼀样的或是相似的,那么,协议会帮你消除重复的部分。HPACK 算法:在客户端和服务器同时维护⼀张头信息表,所有字段都会存⼊这个表,⽣成⼀个索引号,以后就不发送同样字段了,只发送索引号,这样就提⾼速度
  • ⼆进制格式 HTTP/2 不再像 HTTP/1.1 ⾥的纯⽂本形式的报⽂,⽽是全⾯采⽤了⼆进制格式,头信息和数据体都是⼆进制,并且统称为帧(frame):头信息帧和数据帧
  • 数据流、并发传输 HTTP/2 的数据包不是按顺序发送的,同⼀个连接⾥⾯连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。每个请求或回应的所有数据包,称为⼀个数据流( Stream )。每个数据流都标记着⼀个独⼀⽆⼆的编号,其中规定客户端发出的数据流编号为奇数, 服务器发出的数据流编号为偶数。客户端还可以指定数据流的优先级。优先级⾼的请求,服务器就先响应该请求
  • 多路复⽤ HTTP/2 是可以在⼀个连接中并发多个请求或回应,⽽不⽤按照顺序⼀⼀对应。移除了 HTTP/1.1 中的串⾏请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,⼤幅度提⾼了连接的利⽤率
  • 服务器推送 HTTP/2 还在⼀定程度上改善了传统的「请求 - 应答」⼯作模式,服务不再是被动地响应,也可以主动向客户端发送消息

HTTP2 缺点

HTTP/2 主要的问题在于

  • 多个 HTTP 请求在复⽤⼀个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以⼀旦发⽣了丢包现象,就会触发 TCP 的重传机制,这样在⼀个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来

http3 优化

  • http3 基于 UDP 实现 QUIC 协议
  • QUIC 有⾃⼰的⼀套机制可以保证传输的可靠性的。当某个流发⽣丢包时,只会阻塞这个流,其他流不会受影响
  • TLS3 升级成了最新的 1.3 版本,头部压缩算法也升级成了 QPack。
  • HTTPS 要建⽴⼀个连接,要花费 6 次交互,先是建⽴三次握⼿,然后是 TLS/1.3 的三次握⼿。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 3 次
  • 改进的拥塞控制: QUIC 实现了更现代的拥塞控制算法(如 BBR),这有助于在丢包和网络拥塞环境下维持高吞吐量
  • 连接迁移和恢复: QUIC 支持连接迁移,即使客户端的 IP 地址或端口号发生改变,也能够维持原有的连接状态,这对移动设备特别有用
  • 单个数据流的无阻塞传输: 在 HTTP/2 中,如果一条流中的一个数据包丢失,会导致同一 TCP 连接内的所有流被阻塞(头部阻塞),直到丢失的数据包被成功传输。因为 QUIC 的多路径传输是在特定流的级别上实现的,因此单个流中的丢包仅影响该流,不会影响其他并行的流
  • 内置加密: QUIC 把传输层加密作为协议的一部分,而不是叠加到它上面,这简化了加密过程
  • 多路复用不依赖TCP: 虽然 HTTP/2 实现了数据流的多路复用,但依然基于单一的 TCP 连接,QUIC 的多路复用建立在 UDP 上,不受传统 TCP 限制
  • 适用于实时通信: QUIC 的设计考虑到了实时通信需求,它的低延迟特性使得传输更适合视频和音频流等实时数据

TCP的三次握手和四次挥手

  • 三次握手,如果只有两次握手,在server端的 SYN+ACK丢失后,client会重新发起连接,而 server 仍认为连接成功建立。易造成资源浪费
  • 关闭连接时需要四次挥手?这是因为被动关闭端或许还有数据没被送出去(半连接状态),不能像握手时一样,第二次握手既是发起握手也是响应握手。这是由于TCP是可靠双通道的特性导致的

TCP 重传、滑动窗⼝、流量控制、拥塞控制

  • 快重传和快恢复: 假如接收方M1收到了,M2没有收到,之后的M3、M4、M5又发送了,此时接收方一共连续给发送方反馈了3个M1确认报文。那么快重传规定,发送方只要连续收到3个重复确认,立即重传对方发来的M2
  • 滑动窗⼝: 收端将自己可以接收的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK报文来通知发送端,滑动窗口是接收端用来控制发送端发送数据的大小,从而达到流量控制
  • 慢启动和拥塞避免:TCP发送端会维护一个拥塞窗口(congestionwindow),简称为cwnd。拥塞窗口初始为1个报文段,每经过一次RTT(数据完全发送完到确认的时间),窗口大小翻倍(指数增长,只是前期慢)。拥塞避免,它思路是让拥塞窗口cwnd缓慢增大,发送方的cwnd达到阀值ssthresh(初始值由系统决定的)之后,每经过一个RTT就把拥塞窗口加一,而不是加倍(收到两个或四个确认,都是cwnd+1),cwnd呈线性增加(加法增大)

TCP 半连接队列和全连接队列

  • 半连接队列,也称 SYN 队列;
  • 全连接队列,也称 accepet 队列; 服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握⼿的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调⽤ accept 函数时把连接取出来

TCP 内核参数

  • 三次握手中 client SYN 报文丢失重传:重发的次数由 tcp_syn_retries 参数控制,默认是 5 次
  • 三次握手中 server 端要想增⼤半连接队列,不能只单纯增⼤ tcp_max_syn_backlog 的值,还需⼀同增⼤ somaxconn 和 backlog,也就是增⼤ accept 队列。否则,只单纯增⼤ tcp_max_syn_backlog 是⽆效的
  • server 端开启 syncookies 功能就可以在不使⽤ SYN 半连接队列的情况下成功建⽴连接
    • 0 值,表示关闭该功能;
    • 1 值,表示仅当 SYN 半连接队列放不下时,再启⽤它;
    • 2 值,表示⽆条件开启功能 image.png
  • 三次握手中 server 端 SYN + ACK 报文丢失重传,可以调整 tcp_synack_retries
  • TCP 建立失败会被Linux,我们还可以选择向客户端发送 RST 复位报⽂,告诉客户端连接已经建⽴失败。打开这⼀功能需要将 tcp_abort_on_overflow 参数设置为 1
  • 四次挥手,一般情况下,主动方进入FIN_WAIT1 后会快速转为 FIN_WAIT2状态,如果收不到被动房的ACK,内核会定时重发 FIN 报文,其中重发次数由 tcp_orphan_retries 参数控制
  • 四次挥手,如果遇到恶意攻击,服务端的 FIN 报文根本无法发送出去,会导致存在大量半连接状态的孤儿连接,调整 tcp_max_orphans 参数。 新增的孤儿连接将不再走四次挥手,而是直接发送 RST 复位报文强制关闭
  • tcp_max_tw_buckets 参数,当 TIME_WAIT 的连接数量超过该参数时,新关闭的连接就不再经历 TIME_WAIT 而直接关闭

关注公众号,一起交流,微信搜一搜: 潜行前行

欢迎指正文中错误

参考文章

  • 小林图解网络