基本概念
是什么
HTTP: 超文本传输协议,HyperText Transfer Protocol。一个在计算机世界专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
协议:是在计算机世界里,使用计算机能够理解的语言确立的一种计算机之间交流通信的规范(两个以上参与者),以及相关各种控制和错误处理方式(行为约定和规范)。
传输:在两点之间双向传输数据,但允许有中转或接力。
超文本:本身是纯文字文件,但内部用很多标签定义了图片、视频等连接,经过浏览器解析,呈现出有文字和画面的网页。
常见状态码
- 1xx:提示信息,表示目前是协议处理的中间状态,还需要后续的操作
- 2xx:成功,报文已经收到并被正确处理
- 200 ok,如果是非HEAD请求,服务器返回的响应都会有body数据
- 204 no content 与200基本相同,但响应头没有body数据
- 206 partial content 应用于http分块下载或断电续传,表示响应返回的body数据不是资源的全部,而是其中的一部分,也是服务器处理成功的状态
- 3xx:重定向,资源位置发生变动,需要客户端重新发送请求
- 301 moved permanently 永久重定向,说明请求资源已经不存在,需要改用新的URL再次访问
- 302 found 临时重定向,说明请求的资源还在,但是暂时需要用另一个URL来访问。301,301都会在响应头里使用Location字段,指明后续要跳转的URL,浏览器会自动重定向新的URL
- 304 not modified 表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,告诉客户端可以继续使用缓存资源,用户缓存控制
4xx:客户端错误,请求报文错误,服务器无法处理
- 400 bad request 客户端请求报文有错
- 401 unauthorized 要求身份验证
- 403 forbidden 服务器禁止访问资源
- 404 not found 资源不存在
- 405 method not allowed 请求方法被禁止- 5xx:服务器错误,服务器请求时内部发生了错误
- 500 internal server error 服务器错误
- 501 not implemented 功能不支持,敬请期待
- 502 bad gateway 服务器作为网关或代理是返回的错误码,表示服务器自身工作正常,访问后端服务发生了错误,或收到了一个无效响应
- 503 server unavailable 服务繁忙
常见字段
- Host:客户端发送请求时,用来指定服务器的域名,有了host字段,就可以将请求发往同一台机器的不同网站
- Content-Length:服务器返回数据时,会有content-length字段,表名本质回应的数据长度。http协议通过设置回车符、换行符作为header的边界,通过content-length作为body的边界,为了解决粘包问题。
- Connection:常用户客户端要求服务器使用http长连接机制,以便其他请求复用。http1.1默认连接都是长连接,但为了兼容老版本,需要指定Connection为Keep-Alive
- Connection:Keep-Alive
- Content-Type:用户服务器返回时,告诉客户端,本次数据时什么格式
- Accept:*/* 客户端请求时声明自己可以接受哪些数据格式
- Content-Type:text/html;Charset=utf-8 发送的是网页,而且编码是utf-8
- Content-Encoding:说明数据的压缩方法,表示服务区返回数据使用了什么压缩格式
- Accept-Encoding:gzip,default 客户端说明自己接受的压缩方法
- Content-Encoding:gzip 告知客户端用此方法解压
GET和POST
Get:RFC规范,从服务器获取指定的资源,请求的参数一般写在URL中,只允许ASCII字符,而且浏览器会对URL长度有限制(http本身对url长度没有任何规定)
Post:RFC规范,根据请求的负荷(Body)对执勤的资源做出处理,请求携带的数据一般写在body中,body数据可以试任意格式的,浏览器不会对body大小做限制
HTTP缓存技术
对于具有重复性的HTTP请求,可以把这对请求-响应的数据都缓存在本地,http有两种缓存方式:
- 强制缓存:只要浏览器判断缓存没有过期,则直接用浏览器本地缓存,决定是否使用缓存的主动性在浏览器这边
- 强缓存利用Cache-Control(相对时间);Expires(绝对时间)表示客户端缓存的有效期
- 具体实现:服务区在返回资源的同时,在response头部增加Cache-Control并设置过期时间,浏览器再次请求时先看过期时间载决定是够请求服务器
- 协商缓存:304响应码,表示告诉服务器使用本地缓存。
- 第一种:请求头部中的If-Modified-Since(第二次带上第一次的Last-Modified)字段与响应头部中的Last-Modified(资源最后修改时间)字段实现,服务器判定资源是否被改过。
- 第二种:请求头部中的If-None-Match(上次的Etag)字段与Etag(唯一标识响应资源)字段。可以避免由于时间篡改导致的不可靠问题、没有修改文件内容修改时间也可能改变问题、文件在秒级时间内被修改问题、有些服务器不能精确获取文件最后修改时间问题。
只有在未能命中强制缓存的时候,才能发起企鹅上缓存字段的请求
HTTP特性
HTTP1.1优点
- 简单,报文格式就是header+body,头部信息也是key-value形式
- 灵活易于扩展:HTTP协议里请求方法、URI、状态码、头字段等都没有定死,可以自定义和扩展
- https就是在http和tcp之间增加了ssl/tls安全传输层
- 应用广泛和跨平台
HTTP1.1缺点
- 无状态:好处是服务器不需要记录额外信息,减轻负担。坏处是,服务器没有记忆,有关联性操作时会非常麻烦
- 登录>加购物车>下单>支付,都需要身份验证,但服务器不知道,每次都要查一遍身份信息
- 对于无状态问题,可以使用Cookie解决
- 明文传输:方便阅读,但是内容容易被窃取
- 不安全:明文,内容可能被窃听;不验证身份,可能遭遇伪装;无法证明报文完整,可能被篡改
- 用https解决
HTTP1.1性能
- 长连接:http1.0每发起一起请求就建立一次TCP连接,而且是串行请求,增加了通信开销。1.1使用长连接通信,减少重复TCP建连和断开,减轻服务器负载。长时间灭有数据交互或任意一方主动提出,才会断开。
- 管道网络传输:在同一个TCP连接里,客户端可以发起多个请求,只要一个请求出去了,不必等其回来,就可以发起第二个请求,减少整体响应时间。但是服务器必须按照接收请求的顺序发送对应的响应,某个请求耗时长的情况下,后续请求的处理都会被阻塞,成为对头堵塞。所以1.1解决了请求的对头阻塞,没有解决响应的对头阻塞。实际,1.1的管道技术不是默认开启的,且浏览器基本都不支持。
HTTP与HTTPS
- https在tcp和http之间加入了ssl/tls安全协议,使得报文能够加密传输
- https在tcp3次握手后,还需要就行ssl/tls的握手过程,才可以进入加密报文传输
- https需要向CA申请数字证书
- 端口443
HTTPS解决了HTTP的哪些问题
- 窃听:信息加密,对称+非对称 混合加密
- 篡改:校验机制,摘要算法
- 冒充:身份验证,将服务器公钥放到数字证书中
HTTPS如何建立连接
- 客户端向服务器索要并验证服务器公钥
- 双方协商生成会话密秘钥
- 采用会话秘钥进行加密通信
tls的握手阶段涉及四次通信,使用不同秘钥交换算法,握手流程也不一样。
- RSA
- Client Hello,客户端向服务端发起加密通信请求。主要发送 TLS协议版本;客户端生产的随机数Client Random;客户端支持的密码套件列表,如RSA。
- Server Hello,服务端收到客户端请求后,发出响应。主要有确认TLS协议版本,如果不支持则关闭加密通信;服务器生产的随机数Server Random;确认密码套件列表;服务器的数字证书。
- 客户端回应,客户端收到服务器回应后,首先通过CA公钥,确认服务器数字证书的真实性。如果证书没问题,客户端从数字证书去除服务器公钥,然后用它加密报文,向服务器发送如下信息
- 一个随机数pre-master key
- 加密通信算法改变通知,表示随后都将用会话秘钥加密通信
- 客户端握手结束通知,表示客户端握手阶段已经结束。同时把之前所有内容发生的数据做摘要,供服务端校验。
- 服务端和客户端有了以上3个随机数,接着就用双方协商的加密算法,各自生成本质通信的会话秘钥
- 服务器的最后回应,服务器收到随机数pre-master key后,通过协商算法计算本次通信的会话秘钥,之后向客户端发送最后信息:
- 加密通信算法改变通知
- 服务器握手结束通知,表示服务器握手阶段结束。同时把之前所有内筒做摘要,供客户端校验。
- 至此,TLS握手阶段结束,接下来客户端和服务端进入加密通信阶段,完全适用HTTP协议,但是用了会话秘钥加密内容。
HTTP1.1、2、3演变
- 1.1相比1.0提高了什么性能
- 使用长连接改善了1.0短连接造成的性能开销
- 支持管道网络传输,第一个请求发出去后不必等待返回,就可以发出第二个请求,可以减少整体响应时间
- 1.1存在的性能瓶颈
- 请求、响应头部 Header 未经压缩就发送,首部信息越多延迟越大,只能压缩body部分
- 冗长的首部,每次互相发送相同首部造成资源浪费
- 服务器按顺序响应,服务器响应慢,会导致客户端一直请求不到数据,也就是队头阻塞
- 没有请求优先级控制
- 请求只能从客户端开始,服务端被动响应
- http2做了什么优化
- http2是基于https的,安全性有保障
- 头部压缩:如果同时发出多个请求,他们的头是一样或相似的,那么协议会消除重复的部分,。这就是所谓的HPACK算法,客户端和服务端同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不用发送同样的字段了,只发送索引号,提高速度。
- 二进制格式:不再像1.1里纯文本形式的报文,全面采用二进制格式,头信息和数据体都是二进制,并且统称为帧,头信息帧 Headers Frame和数据帧 Data Frame。对人不友好但是对计算机友好,增加了传输效率。
- 并发传输:引入Stream概念,多个Steam复用一条TCP连接。针对不同的HTTP请求用独一无二的StreamID来区分,接收端可以通过StreamID有序组成HTTP消息,不同Stream的帧可以乱序发送,也就是HTTP2可以并行交错的发送请求和响应。
- 服务器主动发送数据:客户端和服务端都可以建立Stream,客户端建立的Stream必须是奇数,服务器建立的Stream必须是偶数
- HTTP2有什么缺陷
- 通过Stream的并发解决了1.1的对头阻塞问题,但是在TCP层还是有“对头阻塞”的问题。TCP必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区的数据返回给HTTP引用,那么当前一个字节数据没有到达时,后收到的字节数据只能存放在内核的缓冲区里,只有等到这一个字节数据到达时,HTTP2应用层才能从内核中拿到数据,这就是HTTP2的对头阻塞问题
- HTTP3做了哪些优化
- TCP换成UDP,UDP发送不管顺序,也不管丢包,所以不会出现像HTTP2的队头阻塞问题,UDP不可靠,但是基于UDP的QUIC协议可以实现类似TCP的可靠传输。QUIC有以下特点:
- 无队头阻塞:QUIC也有Stream与多路复用概念,当某个流丢包时,只会阻塞这个留,其他流不会受到影响,因此不存在对头阻塞问题。与HTTP2不同,HTTP2只要某个流中的数据包丢失,其他流也会受影响。
- 更快建立连接:对弈HTTP1和HTTP2,TCP和TLS是分层的,分别属于内核实现的传输层、openssl实现的表示层,因此它们难合并在一起,需要分批次握手,tcp先握,tls再握。HTTP3在传输数据前虽然需要QUIC协议握手,但是这个握手只需要1RTT,握手的目的是为了确认双方的连接ID,连接迁移就是基于连接ID实现的。HTTP3的QUIC协议并不是与TLS分层,而是QUIC包含了TLS,它在自己的帧携带TLS记录,再加上QUIC使用的是TLS1.3,因此只需要1RTT就可以完成建立连接与密钥协商。甚至在第二次连接的时候,应用数据包可以和QUIC握手信息(连接信息+TLS信息)一起发送,达到0RTT效果
- 连接迁移:TCP通过四元组确定一条连接,而QUIC是通过连接ID来标记通信的两个端点,客户端和服务端可以各自选择一组ID来标记自己,因此移动设备的网络变化后,导致IP地址变了,只要仍保有上下文信息,就可以无缝使用原连接,达到连接迁移的目的