文章目录
HTTP协议
HTTP 协议虽然很常用,也很复杂,重点记住 GET、POST、 PUT、DELETE 这几个方法,以及部分重要的首部字段。
HTTP 请求的准备
- 浏览器会将 www.163.com 这个域名发送给 DNS 服务器,让它解析为 IP 地址。
- HTTP 是基于 TCP 协议的,建立 TCP 连接(三次握手)。
- 目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里,默认是开启 Keep-Alive 的,这样建立的 TCP 连接,就可以在多次请求中复用,利于减少资源的浪费。
HTTP请求的构建
-
请求报文格式
-
HTTP 的报文大概分为三大部分。第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体。
第一部分:请求行
- 在请求行中,URL 就是http://www.163.com ,版本为 HTTP 1.1。
方法有几种类型。
GET
- GET 就是去服务器获取一些资源。
- 对于访问网页来讲,要获取的资源往往是一个页面 或 其他的格式,比如说返回一个 JSON 字符串,返回什么是由服务器端的实现决定的。
POST
- POST是主动告诉服务端一些信息,而非获取。要告诉的信息一般会放在正文里面。正文有各种各样的格式,比如 JSON。
PUT
- PUT 就是上传最新内容。但是,HTTP 的服务器往往是不允许上传文件的,所以 PUT 和 POST 就都变成了要传给服务器东西的方法。
- 在实际使用中,POST 往往是用来创建资源的,而 PUT 往往是用来修改资源的。
- 不常用。
DELETE
- DELETE 就是用来删除资源的。
- 不常用。
第二部分:首部字段
- 请求行下面就是我们的首部字段。首部是 key value,通过冒号分隔。这里面保存一些非常重要的字段。
Accept-Charset(字符集)
- Accept-Charset:表示客户端可以接受的字符集,防止出现乱码。
Content-Type(正文格式)
- Content-Type:是指正文的格式。例如,我们进行 POST 的请求,如果正文是 JSON,那么我们就应该将这个值设置为 JSON。
Cache-control与If-Modified-Since(缓存控制)
-
Cache-control:用来控制缓存,当客户端发送的请求中包含 max-age 指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定 max-age 值为 0,那么缓存层通常需要将请求转发给应用集群。
-
If-Modified-Since:也是关于缓存的。如果服务器的资源在某个时间之后更新了,那么客户端就应该下载最新的资源;如果没有更新,服务端会返回“304 Not Modified”的响应,那客户端就不用下载了,也会节省带宽。
缓存
为啥要使用缓存呢?那是因为一个非常大的页面有很多东西。
-
场景:例如,我浏览一个商品的详情,里面有这个商品的价格、库存、展示图片、使用手册等等。商品的展示图片会保持较长时间不变,而库存会根据用户购买的情况经常改变。如果图片非常大,而库存数非常小,如果我们每次要更新数据的时候都要刷新整个页面,对于服务器的压力就会很大。
-
对于这种高并发场景下的系统,在真正的业务逻辑之前,都需要有个接入层,将这些静态资源的请求拦在最外面。
-
架构如下图。
-
Nginx 这一层,它如何处理 HTTP 协议呢?
- 对于静态资源,有 Vanish 缓存层。当缓存过期的时候,才会访问真正的 Tomcat 应用集群。
- 对于动态资源,有 Redis缓存层。
HTTP 请求的发送
- HTTP 协议是基于 TCP 协议的,所以它使用面向连接的方式发送请求,通过 stream 二进制流的方式传给对方。当然,到了 TCP 层,它会把二进制流变成一个的报文段发送给服务器。
- 详见第14讲 | HTTP协议:看个新闻原来这么麻烦(趣谈网络协议 - 极客时间)
HTTP 响应/返回的构建
- HTTP 的返回报文也是有一定格式的。这也是基于 HTTP 1.1 的。
状态码
- 状态码会反应 HTTP 请求的结果。
- 常见状态码。。。。。。
首部字段
- 接下来是返回首部的key value。
- Retry-After:告诉客户端应该在多长时间以后再次尝试一下。“503 错误”是说“服务暂时不再和这个值配合使用”。
- Content-Type:在返回的头部里也有Content-Type,表示返回的是 HTML,还是 JSON。
HTTP 响应/返回的发送
- 构造好了返回的 HTTP 报文,接下来就是把这个报文发送出去。还是交给 Socket 去发送,还是交给 TCP 层,让 TCP 层将返回的 HTML,也分成一个个小的段,并且保证每个段都可靠到达。
- 这些段加上 TCP 头后会交给 IP 层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。
- 客户端发现 MAC 地址符合、IP 地址符合,于是就会交给 TCP 层。根据序列号看是不是自己要的报文段,如果是,则会根据 TCP 头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。
- 当浏览器拿到了 HTTP 的报文。发现返回“200”,一切正常,于是就从正文中将 HTML 拿出来。HTML 是一个标准的网页格式,浏览器只要根据这个格式,展示出一个绚丽多彩的网页。
以上就是一个正常的 HTTP 请求和返回的完整过程。
HTTP 2.0
HTTP 协议也在不断地进化,在 HTTP1.1 基础上便有了 HTTP 2.0。
HTTP 2.0的特性
压缩表头,建立索引
- HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 的头,而且不考虑 pipeline 模式的话,每次的过程总是像上面那样一去一回。这样在实时性、并发性上都存在问题。
- 为了解决这些问题,HTTP 2.0 会对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。
切分连接为多个流
- 另外,HTTP 2.0 协议将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。
消息和帧
-
HTTP 2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有:
- Header 帧:用于传输 Header 内容,并且会开启一个新的流。
- Data 帧:用来传输正文实体。多个 Data 帧属于同一个流。
-
通过这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。
示例
- 假设我们的一个页面要发送三个独立的请求,一个获取 css,一个获取 js,一个获取图片 jpg。如果使用 HTTP 1.1 就是串行的,但是如果使用 HTTP 2.0,就可以在一个连接里,客户端和服务端都可以同时发送多个请求或回应,而且不用按照顺序一对一对应。
- HTTP 2.0 其实是将三个请求变成三个流,将数据分成帧,乱序发送到一个 TCP 连接中。
HTTP 2.0的优点
队首阻塞问题
- HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题。
无需多条连接即可实现并行
- 不需要通过 HTTP 1.x 的 pipeline 机制用多条 TCP 连接来实现并行请求与响应。
减少TCP连接数
- 减少了 TCP 连接数对服务器性能的影响。
加快页面传输速度
- 将页面的多个数据 css、js、 jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。
参考资料
- HTTP协议与QUIC协议:第14讲 | HTTP协议:看个新闻原来这么麻烦(趣谈网络协议 - 极客时间)
- HTTPS协议:第15讲 | HTTPS协议:点外卖的过程原来这么复杂(趣谈网络协议 - 极客时间)