HTTP
http是目前应用最广泛的应用层协议,截止到目前为止已经发布了多个版本,最常用的是http1.1和http2。
http0.9是最早的版本,功能很简单,没有header,只支持GET。
http1.0
-
只支持短连接,即每次请求一个资源就会新建一次tcp连接,服务器写完响应行后立刻将TCP连接关闭
由于tcp连接的建立和关闭需要经历三次握手和四次握手,再加上tcp慢启动特性,报文一开始不会满负荷传输,所以不仅开销很大,而且效率很低。
-
相比于上一版本,增加了http header,和status code用于声明请求的结果,content-type字段也可以用来声明传输其他文件,头部还增加了协议的版本号。
http1.1是1997年发布的,是现在使用最广泛的版本,这个版本引入了长连接,减少了tcp连接建立和关闭的消耗。
-
新加了connection请求头字段,false表示短连接,keep-alive表示长连接(默认)
在持久连接模式中,由于服务器不会立刻关闭TCP连接,所以需要在响应中加上一个
Content-Length
的响应头来表示响应体的长度,让浏览器判断HTTP响应是否结束。如果没有这个响应头的话,浏览器会处于
pending
的状态,因为在它看来还有数据要接收。
所以长连接无非就是通过Content-Length字段把连接关闭的主动权交给了客户端。
-
支持分块传输编码,可以发送动态数据,只在1.1版本中可以使用
使用分块传输编码,数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小,使得服务器可以发送动态生成的数据。
设置相应头Transfer-Encoding:chunked,此时消息体便由数量未定的块组成,并以最后一个大小为0的块结束。
HTTP/1.1 200 OK\\r\\n\\r\\nTransfer-Encoding: chunked\\r\\n...\\r\\n\\r\\n<chunked 1 length>\\r\\n<chunked 1 content>\\r\\n<chunked 2 length>\\r\\n<chunked 2 content>\\r\\n...\\r\\n0\\r\\n\\r\\n\\r\\n
其他的改变还有增加了Host头,让服务端知道用户请求的是哪个域名等。
2014年,更新了内容,增加了TLS支持,即https传输,除了短连接和长连接模型,还支持服务端push模型,websocket模型。
Http2是2015年发布的,主要就是提升安全性与性能,gRPC底层就是使用的http2协议。
-
多路复用(Multiplexing):就是说 HTTP/2 可以重复使用同一个 TCP 连接,并且连接是多路的,多个请求或响应可以同时传输,这也是gRPC支持客户端流和服务器端流的原因
对比之下,HTTP/1.1 的长连接也能复用 TCP 连接,但是只能串行,不能“多路”。
-
Rest API通常构建在http1.1上,是请求响应模式。如果一个微服务收到多个客户端请求,每次只能处理一个,即使构建在http2上,依旧是请求响应模式,无法发挥http2的优势:多路复用。
gRPC构建在http2上,支持流式通信和双向通信,通过不断流式传输信息同时处理这些请求。但双向流模式依旧需要客户端发起调用。这里的流式通信,不是全双工的,只是将原本的请求响应风格,变为了同时可以发送多个请求,服务器也能发送多个响应。
二进制协议:HTTP/2 的消息头使用二进制格式,而非文本格式。并且使用专门设计的 HPack 算法压缩。
服务器推送:服务端能够直接把资源推送给客户端,当客户端需要这些文件的时候,它已经在客户端了。(HTTP/2推送服务器只能被浏览器来处理,而不是应用)
通讯双方cache一份header filed表,用来差量更新头部字段,避免重复header的传输
HTTP3
2018年发布,基于谷歌的QUIC,底层使用udp代码tcp协议,
这样解决了队头阻塞问题,同样无需握手,性能大大地提升,默认使用tls加密。
WebSocket
websocket是一个双向通信协议,它在握手阶段采用http1.1
握手过程
-
发起握手请求
HTTP/1.1 101 Switching Protocols // 状态行Upgrade: websocket // requiredConnection: Upgrade // requiredSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // required,加密后的 Sec-WebSocket-KeySec-WebSocket-Protocol: chat // 表明选择的子协议
-
服务器如果支持websocket,返回101响应
HTTP/1.1 101 Switching Protocols // 状态行Upgrade: websocket // requiredConnection: Upgrade // requiredSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // required,加密后的 Sec-WebSocket-KeySec-WebSocket-Protocol: chat // 表明选择的子协议
WebSocket 提供两种协议:不加密的
ws://
和 加密的
wss://
. 因为是用 HTTP 握手,它和 HTTP 使用同样的端口:ws 是 80(HTTP),wss 是 443(HTTPS)
HTTP2 vs WebSocket
WebSocket是全双工的,可以双向通信,主要应用在实时通信的场景中,服务器可以实时推送数据给客户端。
HTTP/2 虽然也支持 Server Push,但是服务器只能主动将资源推送到客户端缓存!那不是应用程序可以感知的,主要是让浏览器(用户代理)提前缓存静态资源。
在典型的HTTP 1.x工作流中,浏览器请求一个页面,服务器在响应中返回一个HTML,然后就时等待浏览器解析响应并发送额外请求来获取额外的内嵌资源(JavaScript、CSS等)。服务器推送使服务器能够试探性地向客户端发送资源。此时,浏览器不必解析HTML页面并找到需要加载的其它资源;而是服务器能够立即开始发送它们。
但是人类的想象力是非常丰富的。比如为了让服务器可以推送消息给客户端,使用了一个“偏方”。它就是SSE(Server Sent Event)。SSE是一种让服务器能够在客户端服务器建立连接之后异步推送数据给客户端的机制。由于SSE是基于HTTP的,其天然适配于HTTP/2,这样SSE就可以集两者之长:HTTP/2可以基于多路复用流形成一个高效传输层,同时SSE给应用提供了API使之能够进行推送。
Websocket技术可能会继续使用,但是SSE和其EventSource API同HTTP/2的能力相结合可以在多数场景下达到同样的效果,但是会更简单。