图片 10

http1.0被抱怨最多的就是连接无法复用,带宽和延迟

一分钟预览 HTTP2 特性和抓包分析

2016/09/26 · JavaScript
· HTTP/2

原文出处: 段隆贤   

http2 协议

HTTP/2 源自 SPDY/2,正式版http2规格标准叫做RFC
7540,发布于2015年5月15日。

  • RFC 7540 – Hypertext Transfer Protocol Version 2
    (HTTP/2)

  • RFC 7541 – HPACK: Header Compression for
    HTTP/2

  • fex-team翻译的 htt2
    中英文对照.md)

HTTP/2 跟 SPDY 仍有不同的地方,主要是以下两点:

  1. HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS

  2. HTTP/2 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DELEFT

即使千辛万苦,还是把网站升级到http2了,遇坑如《phpcms
v9站http升级到https加http2遇到到坑》。

前言

互联网世界中,HTTP协议算是使用最广泛的协议。最近Http2.0诞生再次使得互联网技术成为关注的焦点。接下来我们一起看看关于HTTP的那些事。

背景

近年来,http网络请求量日益添加,以下是httparchive统计,从2012-11-01到2016-09-01的请求数量和传输大小的趋势图:

图片 1

 

当前大部份客户端&服务端架构的应用程序,都是用http/1.1连接的,现代浏览器与单个域最大连接数,都在4-6个左右,由上图Total
Requests数据,如果不用CDN分流,平均有20个左右的串行请求。
HTTP2
是1999年发布http1.1后的一次重大的改进,在协议层面改善了以上问题,减少资源占用,来,直接感受一下差异:

HTTP/2 is the future of the Web, and it is
here!
这是 Akamai 公司建立的一个官方的演示,用以说明 HTTP/2 相比于之前的
HTTP/1.1 在性能上的大幅度提升。 同时请求 379 张图片,从Load time
的对比可以看出 HTTP/2 在速度上的优势。

图片 2

 

本文所有源码和抓包文件在github

http2 特点

http2 性能,http2
demo

  • HTTP/2’s binary framing layer

  • Streams, messages, and frames

  • Request and response multiplexing

  • Stream prioritization

  • One connection per origin

  • Flow control

  • Server push

  • Header compression

(1)二进制

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x
的文本格式。二进制协议解析起来更高效。

(2)二进制格式

HTTP/1
的请求和响应报文,都是由起始行、首部和实体正文(可选)组成,各部分之间以文本换行符分隔。

HTTP/2 将请求和响应数据分割为更小的帧,并对它们采用二进制编码。

帧(Frame):HTTP/2 数据通信的最小单位。

消息(Message):指 HTTP/2 中逻辑上的 HTTP
消息。例如请求和响应等,消息由一个或多个帧组成

流(Stream):存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数
ID。

HTTP/2
中,同域名下所有通信都在单个连接上完成,这个连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

Frame 是 HTTP/2 二进制格式的基础,Frame 的基本格式如下

+-----------------------------------------------+
|                 Length (24)                   |
+---------------+---------------+---------------+
|   Type (8)    |   Flags (8)   |
+-+-------------+---------------+-------------------------------+
|R|                 Stream Identifier (31)                      |
+=+=============================================================+
|                   Frame Payload (0...)                      ...
+---------------------------------------------------------------+

字段含义可查看协议

图片 3

http2.png

(3)多路复用

HTTP/1.X 存在线端阻塞(head-of-line blocking)的问题。HTTP/1.1
试过用流水线(pipelining)来解决这个问题,
但是效果并不理想(数据量较大或者速度较慢的响应,
会阻碍排在他后面的请求)。HTTP 管道技术无法大规模使用。

多路复用,代替原来的序列和阻塞机制。就是所有的请求都是通过一个 TCP连接并发完成。流支持优先级流量控制

HTTP/2
的多路复用特性,使得可以在一个连接上同时打开多个流,双向传输数据。每次请求/响应使用不同的
Stream ID。通过 Stream ID 标识,所有的请求和响应都同时跑在一条 TCP
链接上。
当流并发时,就会涉及到流的优先级和依赖。优先级高的流会被优先发送。图片请求的优先级要低于
CSS 和
SCRIPT,这个设计可以确保重要的东西可以被优先加载完。http2上面每个流都拥有自己的公示的流量窗口,它可以限制另一端发送数据。

(4)头压缩

HTTP
1.1请求的大小变得越来越大,有时甚至会大于TCP窗口的初始大小,这会严重拖累发送请求的速度。因为它们需要等待带着ACK的响应回来以后,才能继续被发送。

HTTP/2 对消息头采用 HPACK
(专为http2头部设计的压缩格式)进行压缩传输,能够节省消息头占用的网络的流量。而
HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。

(5)服务端推送

服务端可以在发送页面 HTML
时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把
JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。

服务端可以主动推送,客户端也有权利选择接收与否。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送
RST_STREAM 帧来拒收。

因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1
完全语义,进一步减少了网络延迟。

HTTP

说道HTTP难免会提及TCP协议,HTTP是建立在TCP协议之上的,TCP协议作为传输层协议其实离应用层并不远。

TCP协议的性能直接影响了HTTP:

  • TCP建立连接时需要三次握手1.5个RTT
  • 慢启动(slow start)

目前,影响网路请求的两个主要因素:
带宽和延迟。随着网络基础设施建设带宽得到极大提升,大部分是延迟在影响响应速度。
HTTP 1.0 最大问题:

  • 连接无法复用
  • head-of-line blocking (队头阻塞)

连接无法复用会导致每次都需要进行三次握手和慢启动。

head-of-line blocking 则会导致带宽无法充分利用,以及后续健康请求阻塞。

HTTP/2 源自 SPDY/2

SPDY 系列协议由谷歌开发,于 2009 年公开。它的设计目标是降低 50%
的页面加载时间。当下很多著名的互联网公司都在自己的网站或 APP 中采用了
SPDY 系列协议(当前最新版本是
SPDY/3.1),因为它对性能的提升是显而易见的。主流的浏览器(谷歌、火狐、Opera)也都早已经支持
SPDY,它已经成为了工业标准,HTTP Working-Group 最终决定以 SPDY/2
为基础,开发 HTTP/2。HTTP/2标准于2015年5月以RFC 7540正式发表。

但是,HTTP/2 跟 SPDY 仍有不同的地方,主要是以下两点:

HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
HTTP/2 消息头的压缩算法采用 HPACK ,而非 SPDY 采用的 DEFLATE(感谢网友
逸风之狐指正)

协议文档请见:rfc7540:HTTP2

浏览器和web服务支持情况

http2
支持清单

对于前端开发人员来说,无疑减少了在前端方面的优化工作。比如雪碧图&文件合并||内容内嵌||域名分片

解决连接无法复用问题

在HTTP
1.0协议里设置Connection: Keep-Alive。可以在一定时间内复用连接。对于PC端浏览器来说效果明显,对移动APP来说成效不大。

方案一: 基于TCP的长链接

基于TCP协议,使用TCP的Socket编程技术。 成熟方案如:Google的protobuf。
缺点:实现难度大,需要自己制定协议。
有点:信息的上报和推送变及时,减轻服务器压力。

方案二: http long-polling

客户端在初始状态就会发送一个polling请求到服务器,服务器并不会马上返回业务数据,而是等待有新的业务数据产生的时候再返回。
难度:链接增多会增加服务器压力,移动网络不稳定需要考虑重建链接,稳定性不好,需要业务数据过期机制。

方案三: http streaming

同long-polling不同的是,server并不会结束初始的streaming请求,而是持续的通过这个通道返回最新的业务数据。

方案四:web socket

优点:双向的数据通道,提供了http所缺少的长连接功能。
缺点:较新,大部分浏览器不支持。

HTTP2特性概览

安装部署

从 Nginx 1.9.5 开始,http_v2_module 已经替换了
ngx_http_spdy_module,安装版本用1.10.1

nginx

./configure --with-http_v2_module

mac

brew options nginx
brew install nginx --with-http2

http1.0的缺点

head-of-line blocking

http pipelining
缺点:只适用于http1.1,绝大部分http代理服务器不支持等

1. 二进制协议

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式

图片 4

 

由上图可以看到HTTP2在原来的应用层和HTTP层添加了一层二进制传输。

二进制协议的一个好处是,可以定义额外的帧。

HTTP/2
定义了近十种帧(详情可分析抓包文件),为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
RFC7540:Frame Definitions

图片 5

协议中定义的帧

配置https

HTTP/2 协议本身并没有要求必须基于 TLS 部署,但是 Chrome 和 Firefox
均表示只支持 HTTP/2 Over
TLS。一方面更安全,希望保护以及尊重用户的隐私,一方面利用 TLS
的加密机制可以更好地穿透网络中间节点。需要先配置https。

# 创建一个私钥文件:

openssl genrsa -des3 -out server.key 1024

openssl req -new -key server.key -out server.csr

openssl rsa -in server.key -out server_nopass.key

# 结合密钥和证书生成请求,创建一个自签署的CA证书

openssl req -new -x509 -days 3650 -key server_nopass.key -out server.crt

配置nginx

server
{
    listen 443 ssl http2;
    server_name  www.kailian.com;
    index index.php index.html;
    root  /data/web/www;
    ssl on;
    ssl_certificate /usr/local/etc/nginx/server.crt;
    ssl_certificate_key /usr/local/etc/nginx/server_nopass.key;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    keepalive_timeout 70;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m; 

    charset utf-8;
    location ~ .*\.php$
    {
        include fastcgi.conf;
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
    }

}

http1.0被抱怨最多的就是连接无法复用,和head of line
blocking这两个问题。理解这两个问题有一个十分重要的前提:客户端是依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个。显然连接数并不是越多越好,资源开销和整体延迟都会随之增大。

其他技术

  • Spriting (图片合并)
  • Inlining (内容内嵌)
  • Concatenation (文件合并)
  • Domain Sharding (域名分片)

2. 多路复用

HTTP/2
复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”(见TCP/IP详解卷一)。
每个 Frame Header 都有一个 Stream ID
就是被用于实现该特性。每次请求/响应使用不同的 Stream ID。就像同一个 TCP
链接上的数据包通过 IP: PORT 来区分出数据包去往哪里一样。

图片 6

rfc7540: HTTP2
Multiplexing中对Multiplexing的说明

Streams and Multiplexing A “stream” is an independent, bidirectional
sequence of frames exchanged between the client and server within an
HTTP/2 connection. Streams have several important characteristics: o A
single HTTP/2 connection can contain multiple concurrently open streams,
with either endpoint interleaving frames from multiple streams. o
Streams can be established and used unilaterally or shared by either the
client or server. o Streams can be closed by either endpoint. o The
order in which frames are sent on a stream is significant. Recipients
process frames in the order they are received. In particular, the order
of HEADERS and DATA frames is semantically significant. o Streams are
identified by an integer. Stream identifiers are assigned to streams by
the endpoint initiating the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Streams and Multiplexing
 
   A "stream" is an independent, bidirectional sequence of frames
   exchanged between the client and server within an HTTP/2 connection.
   Streams have several important characteristics:
 
   o  A single HTTP/2 connection can contain multiple concurrently open
      streams, with either endpoint interleaving frames from multiple
      streams.
 
   o  Streams can be established and used unilaterally or shared by
      either the client or server.
 
   o  Streams can be closed by either endpoint.
 
   o  The order in which frames are sent on a stream is significant.
      Recipients process frames in the order they are received.  In
      particular, the order of HEADERS and DATA frames is semantically
      significant.
 
   o  Streams are identified by an integer.  Stream identifiers are
      assigned to streams by the endpoint initiating the stream.

测试

chrome插件

ssllabs查看https配置是否够快

在 Chrome 地址栏输入chrome://net-internals/#http2,打开 Chrome 自带的
HTTP/2 查看工具,可查看 HTTP/2 帧信息

Wireshark抓包查看

连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。

SPDY

为了解决http1.0和1.1存在的问题,Google在2012年提出了SPDY方案。

目标:

  • 降低延迟,客户单的单链接单请求,server的FIFO响应队列都是延迟的大头。
  • http 最初是客户端发请求,服务器响应,服务器无法主动push内容。
  • 压缩http header。

SPDY设计:

位于HTTP之下,TCP和SSL之上,兼容老版本,还可以使用已有的SSL功能。SPDY分为基础功能和高级功能,基础功能默认开启,高级功能手动开启。

3. 数据流

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2
可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

相关资料

  • http2
    讲解

  • http2 home

  • http2
    专题

  • 【协议分析】HTTP2优势分析

head of line
blocking
会导致带宽无法被充分利用,以及后续健康请求被阻塞。假设有5个请求同时发出,对于http1.0的实现,在第一个请求没有收到回复之前,后续从应用层发出的请求只能排队,请求2,3,4,5只能等请求1的response回来之后才能逐个发出。一旦请求1的request因为什么原因没有抵达服务器,或者response因为网络阻塞没有及时返回,影响的就是所有后续请求,问题就变得比较严重了。

基础功能

  • 多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式。解决了队头阻塞,降低了延迟提高带宽利用率。
  • 请求优先级(request
    prioritization)。在多路复用的时候会出现关键请求被阻塞。SPDY
    允许每次request设置优先级。
  • header压缩。压缩率达到80%以上。

4. 头信息压缩:

HTTP/2 对消息头采用
HPACK
进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x
每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。
HTTP2对http头建立索引表,相同的头只发送hash
table 的index, 同时还用了霍夫曼编码和传统的gzip压缩。

对于http1.0的缺点优化方案

高级功能

  • server推送(server push) 。开启server push
    之后,服务器通过X-Associated-Content header告知客户端有新内容推送过来。
  • server暗示(server hint) 。不推送,只提示有新内容。

5. 服务器推送

服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS
文件推送给客户端,而不需要客户端解析 HTML
再发送这些请求。当客户端需要的时候,它已经在客户端了。

那么存在一个问题,如果客户端设置了缓存怎么办。有三种方式(来自社区)

  • 客户端可以通过设置SETTINGS_ENABLE_PUSH为0值通知服务器端禁用推送
  • 发现缓存后,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。
  • cache-digest(提案)

    rfc7540: HTTP2 Server
    Push

    #### 6. 流优先级

    HTTP2允许浏览器指定资源的优先级。

    rfc7540: Stream
    Priority

解决连接无法复用

HTTP 2.0

SPDY的诞生和表现说明了两件事:

  • 一是现有互联网设施基础和http协议广泛使用的前提下,可以通过修改协议层来优化http1.x。
  • 针对http1.x的修改业界反馈很好

优点: 多路复用,请求压缩,优先级控制,server push等亮点。

浏览器支持

主流浏览器都只支持 HTTP/2 Over TLS

http1.0协议头里可以设置Connection:Keep-Alive。在header里设置Keep-Alive可以在一定时间内复用连接,具体复用时间的长短可以由服务器控制,一般在15s左右。到http1.1之后Connection的默认值就是Keep-Alive,如果要关闭连接复用需要显式的设置Connection:Close。一段时间内的连接复用对PC端浏览器的体验帮助很大,因为大部分的请求在集中在一小段时间以内。但对移动app来说,成效不大,app端的请求比较分散且时间跨度相对较大。所以移动端app一般会从应用层寻求其它解决方案,长连接方案或者伪长连接方案:

HTTP2.0主要改动

  1. 新的二进制格式
    http1.x诞生的时候使用明文协议,三部分组成:start line, header,
    body。协议解析,基于文本的,基于文本的协议解析存在缺陷,需要考虑的场景很多。

    http2.0
    采用二进制格式,实现方便且健壮。http2.0的格式定义更接近tcp层的方式。

    • length:定义了整个frame的开始到结束。
    • type:定义frame的类型(一共10种)
    • flags: 用bit位定义一些重要的参数
    • stream ID 用作流控制
    • payload: request的正文
  2. 连接共享(多路复用)

    使用上面提到的Stream
    id用来作连接共享机制的。一个request对应一个stream并分配一个id,接收方可以根据id区分frame归属哪个不同的frame。可以调整优先级,并且可以动态调整。

  3. header压缩

  4. 重置连接表现更好

  5. Server Push

    http2.0能通过push方式将客户端需要的内容预先推送出去,所以也叫“cache
    push”.

  6. 流量控制(Flow control)

  7. 更安全的SSL

node中启用http2

node中可以用spdy模块来启动应用,spdy的api,与https是一致的且主流浏览器只支持HTTP/2
Over TLS,需要配置 私钥和证书,本地自签名服务器配置可参考引用6,7

JavaScript

const express = require(‘express’); const fs = require(‘fs’); const
http2 = require(‘spdy’); const path = require(‘path’); const options = {
key: fs.readFileSync(‘./keys/privatekey.pem’), cert:
fs.readFileSync(‘./keys/certificate.pem’) }; const app = new express();
http2 .createServer(options, app) .listen(8080, ()=>{
console.log(`Server is listening on . You can
open the URL in the browser.`) } ) app.use(“/”,(req,res)=>{
res.send(“hello http2!”); })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const express = require(‘express’);
const fs =  require(‘fs’);
const http2 = require(‘spdy’);
const path = require(‘path’);
const options = {
    key: fs.readFileSync(‘./keys/privatekey.pem’),
    cert: fs.readFileSync(‘./keys/certificate.pem’)
};
const app = new express();
http2
  .createServer(options, app)
  .listen(8080, ()=>{
    console.log(`Server is listening on https://localhost:8080.
     You can open the URL in the browser.`)
  }
)
app.use("/",(req,res)=>{
    
  res.send("hello http2!");
})

如上,对于已存在的项目只要修改几行代码就可以使用http2.0了。

请求头和响应头:

说明:新版的Chrome,对不安全的证书(如本地的自签名服务)会降级到http1.1,firefox不会出现此问题。

启动server push

JavaScript

app.get(“/”,(req,res)=>{ var stream = res.push(‘/app.js’, {
//服务器推送 status: 200, // optional method: ‘GET’, // optional
request: { accept: ‘*/*’ }, response: { ‘content-type’:
‘application/javascript’ } }) stream.on(‘error’, function() { })
stream.end(‘console.log(“http2 push stream, by Lucien “);’)
res.send(`hello http2! <script
src=”/app.js”></script>`);//express 并没有host static
,这个app.js 来自push })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
app.get("/",(req,res)=>{
    var stream = res.push(‘/app.js’, {   //服务器推送
    status: 200, // optional
    method: ‘GET’, // optional
    request: {
      accept: ‘*/*’
    },
    response: {
      ‘content-type’: ‘application/javascript’
    }
  })
  stream.on(‘error’, function() {
  })
  stream.end(‘console.log("http2 push stream, by Lucien ");’)
 
  res.send(`hello http2!
    <script src="/app.js"></script>`);//express 并没有host static ,这个app.js 来自push
})

源码在github

响应

方案一:基于tcp的长链接

移动端的HTTP现状

抓包分析

可以用chrome
内部自带的工具(chrome://net-internals/)查看http2流量,但这个包信息量比较少,结构不如我们熟悉的Fiddler%E6%9F%A5%E7%9C%8Bhttp2%E6%B5%81%E9%87%8F,%E4%BD%86%E8%BF%99%E4%B8%AA%E5%8C%85%E4%BF%A1%E6%81%AF%E9%87%8F%E6%AF%94%E8%BE%83%E5%B0%91%EF%BC%8C%E7%BB%93%E6%9E%84%E4%B8%8D%E5%A6%82%E6%88%91%E4%BB%AC%E7%86%9F%E6%82%89%E7%9A%84Fiddler)
or Wireshark清晰。

Fiddler是直接作为中间代理,可以作为客户端直接与服务端通讯,可以像浏览器那样直接解密https,直接看到https报文,
但是由于受限于.NET
Framework暂不支持Http2.

用wireshark直接抓包 https:443端口的流量是这样的:

数据被加密了,协议细节完全看不到。
这里介绍了一种方法获取私钥解包。
抓包https包时要把代理关了,不然私钥不是同一个,wireshark不能解包(被这个坑了两小时T
T)。

一个包内有多个不同的Steam ID

追踪解密后TCP流可以看到,由于多路复用,各个不同的请求交替传输不同的帧,所以流数据是乱的。但在同一帧内数据还是正常的。

现在越来越多的移动端app都会建立一条自己的长链接通道,通道的实现是基于tcp协议。基于tcp的socket编程技术难度相对复杂很多,而且需要自己制定协议,但带来的回报也很大。信息的上报和推送变得更及时,在请求量爆发的时间点还能减轻服务器压力(http短连接模式会频繁的创建和销毁连接)。不止是IM
app有这样的通道,像淘宝这类电商类app都有自己的专属长连接通道了。现在业界也有不少成熟的方案可供选择了,google的protobuf就是其中之一。

iOS下http现状

iOS系统从iOS8开始通过NSURLSession来支持SPDY,在iOS9+开始支持HTTP2.0.新版本的ATS默认支持https进行网络传输。

最后

最后,HTTP2有更高的传输速度,更少的资源占用,可以去除各种性能优化tricks(如css
sprite,inline-image.)
转向WEB开发的美好未来T.T

方案二:http long-polling

Android下HTTP现状

http2.0只能在新系统中支持,SPDY作为过渡方案存在。

参考资料

  1. Turn-on HTTP/2 today!
  2. Hypertext Transfer Protocol Version 2
    (HTTP/2)
  3. npm spdy
  4. npm spdy push
  5. How to create a self-signed SSL
    Certificate
  6. HPACK: Header Compression for
    HTTP/2
  7. 用Node.js创建自签名的HTTPS服务器

    1 赞 收藏
    评论

图片 7

客户端在初始状态就会发送一个polling请求到服务器,服务器并不会马上返回业务数据,而是等待有新的业务数据产生的时候再返回。所以连接会一直被保持,一旦结束马上又会发起一个新的polling请求,如此反复,所以一直会有一个连接被保持。服务器有新的内容产生的时候,并不需要等待客户端建立一个新的连接。做法虽然简单,但有些难题需要攻克才能实现稳定可靠的业务框架:

结束

HTTP1.x到SPDY,再到HTTP2.0的一些主要变迁技术点。

和传统的http短链接相比,长连接会在用户增长的时候极大的增加服务器压力

移动端网络环境复杂,像wifi和4g的网络切换,进电梯导致网络临时断掉等,这些场景都需要考虑怎么重建健康的连接通道。

这种polling的方式稳定性并不好,需要做好数据可靠性的保证,比如重发和ack机制。

polling的response有可能会被中间代理cache住,要处理好业务数据的过期机制。

图片 8

long-polling方式还有一些缺点是无法克服的,比如每次新的请求都会带上重复的header信息,还有数据通道是单向的,主动权掌握在server这边,客户端有新的业务请求的时候无法及时传送。

方案三:http streaming

同long-polling不同的是,server并不会结束初始的streaming请求,而是持续的通过这个通道返回最新的业务数据。显然这个数据通道也是单向的。streaming是通过在server
response的头部里增加”Transfer Encoding:
chunked”来告诉客户端后续还会有新的数据到来。除了和long-polling相同的难点之外,streaming还有几个缺陷:

有些代理服务器会等待服务器的response结束之后才会将结果推送到请求客户端。对于streaming这种永远不会结束的方式来说,客户端就会一直处于等待response的过程中。

业务数据无法按照请求来做分割,所以客户端没收到一块数据都需要自己做协议解析,也就是说要做自己的协议定制。

streaming不会产生重复的header数据。

方案四:web socket

WebSocket和传统的tcp
socket连接相似,也是基于tcp协议,提供双向的数据通道。WebSocket优势在于提供了message的概念,比基于字节流的tcp
socket使用更简单,同时又提供了传统的http所缺少的长连接功能。不过WebSocket相对较新,2010年才起草,并不是所有的浏览器都提供了支持。各大浏览器厂商最新的版本都提供了支持。

解决head of line blocking

Head of line
blocking(以下简称为holb)是http2.0之前网络体验的最大祸源。健康的请求会被不健康的请求影响,而且这种体验的损耗受网络环境影响,出现随机且难以监控。为了解决holb带来的延迟,协议设计者设计了一种新的pipelining机制。

图片 9

不过pipelining并不是救世主,它也存在不少缺陷:

pipelining只能适用于http1.1,一般来说,支持http1.1的server都要求支持pipelining。

只有幂等的请求能使用pipelining,非幂等请求比如POST不能使用,因为请求之间可能会存在先后依赖关系。

head of line
blocking并没有完全得到解决,server的response还是要求依次返回,遵循FIFO(first
in first
out)原则。也就是说如果请求1的response没有回来,2,3,4,5的response也不会被送回来。

绝大部分的http代理服务器不支持pipelining。

和不支持pipelining的老服务器协商有问题。

可能会导致新的Front of queue blocking问题。

正是因为有这么多的问题,各大浏览器厂商要么是根本就不支持pipelining,要么就是默认关掉了pipelining机制,而且启用的条件十分苛刻。可以参考chrome对于pipeling的问题描述。

HTTP2的优势

二进制分帧

http1.x诞生的时候是明文协议,其格式由三部分组成:start line(request
line或者status
line),header,body。要识别这3部分就要做协议解析,http1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑http2.0的协议解析决定采用二进制格式,实现方便且健壮。

http2.0用binary格式定义了一个一个的frame,和http1.x的格式对比如下图:

图片 10

http2.0的格式定义更接近tcp层的方式,这张二机制的方式十分高效且精简。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章