今天是年3月12日,是万维网诞生30周年的纪念日,搜索引擎巨头谷歌为此在首页换上了互联网发明的Logo以此来纪念万维网诞生30周年。
此外,今天早上,著名的开源Web服务器厂商Nginx宣布被F5收购。我觉得今天可以和大家分享下互联网的那些历史。
我们今天之所以可以在网络上畅游,都要感谢一个人,他就是被誉为互联网之父的英国计算机科学家——蒂姆·伯纳斯·李。
年6月至12月间,伯纳斯·李在日内瓦的CERN(欧洲核子研究组织)担任独立承包人,在那段时间里,他提出了一个构想:创建一个以超文本系统为基础的项目,其目的是方便研究人员分享及更新信息。
Info.cern.ch是世界上第一个网站及网站服务器,网站在一台位于CERN的NeXT计算机上运作,于年8月6日上线。
伯纳斯·李发明的超文本传输控制协议,就是我们今天熟悉的HTTP协议。目前HTTP协议的最新版本是HTTP/2,HTTP协议是互联网的基础协议——可以说,没有HTTP协议就没有我们今天的互联网。
HTTP协议采用BS架构,也就是浏览器到服务器的架构。客户端通过浏览器发送HTTP请求给服务器,服务器经过解析响应客户端的请求。
HTTP是基于TCP/IP协议的应用层协议。在OSI七层模型中在最上层,它并不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。
HTTP协议最早的一个版本是年发布的HTTP/0.9,这个版本只有一个命令,GET。通过GET你可以获取服务器的资源,比如请求服务器根目录下的index.html文件。
GET/index.html
服务器则会返回给客户端index.html的内容,并通过客户端浏览器进行渲染和解析html标签。这个版本的协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。也就是说今天的图像、视频等多媒体资源在HTTP/0.9这个版本上是无法进行传输的。
htmlbodyHelloWorld/body/html
年5月,HTTP/1.0版本发布,增加了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。
这个版本通过HTTP协议任何格式的内容都可以发送,包括传输文字,图像、视频、文件。这为互联网的大发展奠定了基础。
HTTP/1.0除了增加了请求方法以及对发送文件的支持之外,还增加了格式的改变。除了数据部分,每次通信都必须包括头信息(HTTPheader),用来描述一些元数据。另外还增加了状态码、多字符集支持、多部分发送(multi-parttype)、权限(authorization)、缓存(cache)、内容编码(contentencoding)等等。
一个正常的HTTP请求和响应包括请求的网址、请求方法、状态码、HTTP协议版本、请求头和响应头。例如下图所示,请求Google的HTTP消息头所示:
在字符的编码问题上,HTTP/1.0版规定,头信息必须是ASCII码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。
text/htmltext/cssimage/jpegimage/pngimage/svg+xmlaudio/mp4video/mp4application/javascriptapplication/pdf
这些数据类型总称为MIMEtype,每个值包括一级类型和二级类型,之间用斜杠分隔。
此外,由于HTTP/1.0还可以对数据进行压缩后传输,如下所示即为通过Content-Encoding字段说明数据的压缩方法,表示使用gzip压缩数据:
Content-Encoding:gzip
HTTP/1.0版也并不是完美的,它的主要缺点是,每一次建立TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。如果多次请求,势必就会造成频繁的对服务器进行请求而对服务器产生较大的资源损耗。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。
Connection:keep-alive
这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。但是这个并不是一个统一的标准。
年1月,HTTP/1.1版本发布,这个版本只比1.0版本晚了半年。它进一步完善了HTTP协议,一直用到了今天,直到现在还是最流行的版本。
这个版本最大的变化就是将持久化连接加入了HTTP标准,即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection:keep-alive。客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection:close,明确要求服务器关闭TCP连接。此外,HTTP/1.1版还新增了许多方法,例如:PUT、PATCH、HEAD、OPTIONS、DELETE。另外,客户端请求的头信息新增了Host字段,Content-Length字段、管道机制等新特性。
HTTP1.1版虽然允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为队头堵塞。
为了解决这个问题,年,谷歌公开了自行研发的SPDY协议,这个协议在Chrome浏览器上证明可行以后,就被当作HTTP/2的基础,主要特性都在HTTP/2之中得到继承。
年,HTTP/2发布。它不叫HTTP/2.0,是因为标准委员会不打算再发布子版本了。HTTP/2增加了二进制分帧、多路复用、服务器推送(serverpush)、头部压缩等特性。
HTTP/2采用二进制格式传输数据,而非HTTP1.x的文本格式,二进制协议解析起来更高效。HTTP/1的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
多路复用,代替原来的序列和阻塞机制。所有请求都是通过一个TCP连接并发完成。HTTP1.x中,如果想并发多个请求,必须使用多个TCP链接,且浏览器为了控制资源,还会对单个域名有6-8个的TCP链接请求限制。
在HTTP/2中,有了二进制分帧之后,HTTP/2不再依赖TCP链接去实现多流并行了,在HTTP/2中:
同域名下所有通信都在单个连接上完成;单个连接可以承载任意数量的双向数据流;数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。
这一特性,使性能有了极大提升:
同个域名只需要占用一个TCP连接,消除了因多个TCP连接而带来的延时和内存消耗;单个连接上可以并行交错的请求和响应,之间互不干扰;在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级,数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。
服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。
HTTP/3是即将到来的第三个主要版本的HTTP协议。
在HTTP/3中,将弃用TCP协议,改为使用基于UDP协议的QUIC协议实现。QUIC协议是google开发的一套协议,IETF中的QUIC工作组致力于创建QUIC传输协议。QUIC是基于UDP实现的协议,是用来替换TCP的。QUIC协议最初是由Google发起的项目,后面慢慢成为了HTTP/2-encrypted-over-UDP协议。