欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一个不了解HTTP协议的程序员不是一个好的Web开发者

程序员文章站 2022-07-14 20:53:21
...
引言


  说来惭愧,虽然一直在做Web开发,却没有去认真了解过HTTP协议。恰好最近在回顾、总结整个Web开发的知识体系,那么就从万维网(WWW)的基础协议HTTP开始,走进并了解它。

概念


超文本传输协议(HyperText Transfer Protocol,HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。

  提到http,我们必须要知道一个人 :Tim Berners Lee ——万维网的发明者、图灵奖获得者。1990年12月25日,他成功利用互联网实现了HTTP客户端与服务器的第一次通讯。
  那么到底什么是“超文本”,超文本是用超链接的方式把文本组织在一起,最初只是用它来传输文档,发展至今,已经有了巨大的变化。HTTP协议的发展大致如下:


一个不了解HTTP协议的程序员不是一个好的Web开发者


发展


HTTP/0.9

  作为第一个被正式发布的协议版本是 0.9(1991年公布),整个协议非常简单,只有一个GET方法。

GET /index.html

  服务器端响应请求:

<html>
  <body>Hello World</body>
</html>

  客户端发送请求,服务器收到请求返回HTML,传输完毕后服务器自动断开TCP连接。可以看得出,HTTP/0.9有以下特点:

  • 没有请求头
  • 只有GET方法
  • 只响应HTML格式数据

HTTP/1.0

  1996年,HTTP/1.0发布了,相比于0.9版本有了很大的改进。

  它的请求(request )和响应(responses)格式有了变化,除了数据部分都必须添加头信息,用来描述请求与响应的基本信息。客户端请求除了 GET、新添加了 POSTHEAD 方法。现在服务器不仅仅可以响应HTML文件,还支持图片、视频、二进制文件等数据。
  新版的HTTP协议,请求和响应都由两部分组成。headers部分使用ASCII编码,但是服务器可以响应任何类型的数据,因此使用Content-Type来描述数据格式。客户端使用Accept字段表示可以接收的数据类型。

  除此之外,还包括了状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等功能。比如我们所熟悉的404错误,在HTTP/1.0就有了。


  一个简单的客户端请求可能如下所示:

GET /index.html HTTP/1.0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: */*

  服务器响应:

HTTP/1.0 200 OK 
Content-Type: text/html
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

  HTTP/1.0 有一个重要的缺点是:每个TCP连接只能处理一个请求。我们知道TCP是面向连接的网络协议,数据传输较安全,因此在建立连接时需要进行“三次握手”。如果每一个请求都建立一次连接,时间成本非常大,如果请求大量的外部资源,延迟会非常严重。

  针对这个问题,有的浏览器允许在请求头添加一个新的字段来复用TCP连接,但它并没有被广泛支持,问题仍然没有完全被解决。

Connection: keep-alive

HTTP/1.1

  三年后(1999年),在1.0的基础上发布了HTTP/1.1,至今仍是使用最多的版本。主要有以下改变:

  • 默认开启了持久连接,解决了1.0版本TCP连接使用效率不高的问题,需要手动关闭。
Connection: close
  • 添加了 PUT, PATCH, OPTIONS, DELETE 方法。

  • 请求头必须使用 Host 字段,否则服务器会返回400错误。它意味着可以访问同一台服务器上的不同网站。

  • 在持久连接的基础上实现了流水线机制(Pipelining ),即在同一个TCP连接中,客户端可以同时发送多个请求,可以看做是异步请求,而无需等待服务器响应。但是服务器必须按照请求的先后顺序进行响应,有一个响应队列。

  • 那么在一个持久连接中,客户端如何知道一个请求已经结束,另一个请求开始传输。因此在连接中使用了一个长度字段来标识服务器一个响应的结束和下一个响应的开始。

Content-Length: 5841
  • 如果是静态页面的话,服务器很容易计算数据的长度,但是对于动态页面来讲,Content-Length 并不是一个好方法。因此还允许使用一个分块传输的方法(Chunked Transfers)。数据由若干个数据块串连而成,由一个标明长度为0的数据块标示结束。
Transfer-Encoding: chunked

  虽然相比于之前的版本,HTTP/1.1有了很大的提高,但是随着网络的迅速发展,它的劣势也渐渐显露出来。HTTP/1.1使用了持久连接来减少连接TCP连接的成本,但是服务器对于同一个TCP连接中的请求仍然是按照前后顺序进行处理的。这就可能会出现堵塞的情况。

  为了克服1.1的这个缺点,优化数据传输速度,开发者使用了很多小技巧。比如合并JavaScript、CSS文件,使用雪碧图等来减少请求个数。

HTTP/2

  2009年,Google 为了解决 HTTP1.1 传输效率不高的问题,提出了 SPDY(speedy)。后来SPDY开发组的成员全程参与了HTTP/2的制定过程,与2015年推出了 HTTP/2。


  • 二进制协议 HTTP/1.X 数据部分可以是任何格式,但是头信息只能是文本(使用ASCII编码)。HTTP/2无论是header还是body都采用二进制格式,把原来http1.x 的header和body部分用帧(frame)重新封装了一层而已,更容易解析和拓展。


    一个不了解HTTP协议的程序员不是一个好的Web开发者

  • 消息头压缩传输 HTTP是无状态协议,每次请求都必须附上所有信息。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,比如Cookie和User Agent,浪费了很多带宽资源。除了对头信息进行压缩,还分别在客户端和服务器进行了缓存,之后传输只发送索引号。


    一个不了解HTTP协议的程序员不是一个好的Web开发者

  • 多路复用 客户端和浏览器都可以同时发送多个请求或回应,解决了HTTP/1.1的“线头堵塞”问题。

  • 服务器推送 不仅仅是客户端发出请求,服务器再进行响应,现在服务器可以主动向客户端推送数据了。比如服务端可以主动推送客户端所需文件。当客户端需要的时候,它已经在客户端了。


  HTTP/2 在多资源请求时速度非常快,akamai 做了一个效果对比的demo,有兴趣可以看一下:https://http2.akamai.com/demo。目前各大主流浏览器都已经支持了HTTP/2,相信未来的发展会更迅速。

小结


  本文主要总结了一下HTTP协议的发展历程,以及个版本之间的重大差异。对于每个版本并没有深入学习与分析,如果想要针对某个版本仔细研究还请查看官方文档。时间、水平有限,文章有错误的地方还请指出。

参考资料: