深刻浅出:5G和HTTP

本文将会讲到5G和HTTP。曾经在深刻浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 3 提到为何有些RPC框架不选用HTTP,而5G会采用HTTP。html

您能够从本文里获取到一些概念:5G用HTTP做为reference point interface的实现,HTTP/2,RESTful API/HATEOAS/OpenAPI等最佳实践和标准,这些都是一些常见可是又容易忽略的知识点。java

本文参考了一些文章,见文章末尾的连接列表。git

HTTP的优势和缺点

咱们你们知道HTTP协议包含的信息太多,太繁重,致使消息体会很大,可是其中有一些消息根本用不上,这也是为何HTTP/1.1消息效率不高的缘由,因此一些RPC框架舍弃它,例如dubbo定义本身的协议等,若是你们定义过协议,例如相似TCP协议,就能明白协议定义的重要性。若是要效率高,消息短,那就会太底层,如TCP,若是要想易于理解,例如HTTP,那就得长一些。github

5G和HTTP

5G明年试商用,在5G里采用HTTP协议,确实有意思。能够参看TS 29.501协议 5G System;Principles and Guidelines for Services Definition,Stage 3。先看看下图:面试

在通讯领域,由原来的Diameter,AAA等转变为HTTP,的确是一个大变化,可是开发的效率将会大大提升。spring

那么5G将会应用到什么HTTP相关技术呢?json

  1. HTTP/2/0 (协议下载https://http2.github.io/http2-spec/)
  2. JSON
  3. HATEOAS
  4. RESTful
  5. OpenAPI

HTTP/2.0

仍是先看看HTTP/2吧。谈到HTTP/2,最早想到Google的SPDY,它是HTTP/2的前身。为何Google要作SPDY呢?缘由很简单,HTTP的效率不高。自从有了SPDY后,加载时间减小64%(http://dev.chromium.org/spdy/spdy-whitepaper),原话这么说的, In lab tests, we have compared the performance of these applications over HTTP and SPDY, and have observed up to 64% reductions in page load times in SPDY.api

SPDY并不用于取代HTTP,它只是修改了HTTP的请求与应答在网络上传输的方式;这意味着只需增长一个SPDY传输层,现有的全部服务端应用均不用作任何修改。 当使用SPDY的方式传输,HTTP请求会被处理、标记简化和压缩。好比,每个SPDY端点会持续跟踪每个在以前的请求中已经发送的HTTP报文头部,从而避免重复发送还未改变的头部。而还未发送的报文的数据部分将在被压缩后被发送。浏览器

HTTP/2主要特性包括:服务器

 

二进制协议

HTTP/1.1 版的头信息确定是文本(ASCII编码),数据体能够是文本,也能够是二进制。HTTP/2 则是一个完全的二进制协议,头信息和数据体都是二进制,而且统称为"帧"(frame):头信息帧和数据帧。

二进制协议的一个好处是,能够定义额外的帧。HTTP/2 定义了近十种帧,为未来的高级应用打好了基础。若是使用文本实现这种功能,解析数据将会变得很是麻烦,二进制解析则方便得多。

 

多工

HTTP/2 复用TCP链接,在一个链接里,客户端和浏览器均可以同时发送多个请求或回应,并且不用按照顺序一一对应,这样就避免了"队头堵塞"。

举例来讲,在一个TCP链接里面,服务器同时收到了A请求和B请求,因而先回应A请求,结果发现处理过程很是耗时,因而就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。

这样双向的、实时的通讯,就叫作多工(Multiplexing)。

 

数据流

由于 HTTP/2 的数据包是不按顺序发送的,同一个链接里面连续的数据包,可能属于不一样的回应。所以,必需要对数据包作标记,指出它属于哪一个回应。

HTTP/2 将每一个请求或回应的全部数据包,称为一个数据流(stream)。每一个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪一个数据流。另外还规定,客户端发出的数据流,ID一概为奇数,服务器发出的,ID为偶数。

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

客户端还能够指定数据流的优先级。优先级越高,服务器就会越早回应。

 

头信息压缩

HTTP 协议不带有状态,每次请求都必须附上全部信息。因此,请求的不少字段都是重复的,好比CookieUser Agent,如出一辙的内容,每次请求都必须附带,这会浪费不少带宽,也影响速度。

HTTP/2 对这一点作了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzipcompress压缩后再发送;另外一方面,客户端和服务器同时维护一张头信息表,全部字段都会存入这个表,生成一个索引号,之后就不发送一样字段了,只发送索引号,这样就提升速度了。

 

服务器推送

HTTP/2 容许服务器未经请求,主动向客户端发送资源,这叫作服务器推送(server push)。

常见场景是客户端请求一个网页,这个网页里面包含不少静态资源。正常状况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器能够预期到客户端请求网页后,极可能会再请求静态资源,因此就主动把这些静态资源随着网页一块儿发给客户端了。 

我给本身挖个坑,后面专门出一篇文章写HTTP/2.

HATEOAS 约束

HATEOAS(Hypermedia as the engine of application state)是 REST 架构风格中最复杂的约束,也是构建成熟 REST 服务的核心。它的重要性在于打破了客户端和服务器之间严格的契约,使得客户端能够更加智能和自适应,而 REST 服务自己的演化和更新也变得更加容易。

在介绍 HATEOAS 以前,先介绍一下 Richardson 提出的 REST 成熟度模型。该模型把 REST 服务按照成熟度划分红 4 个层次:(这个能够参考Richardson的成熟度模型,见后文连接)

  • 第一个层次(Level 0)的 Web 服务只是使用 HTTP 做为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。
  • 第二个层次(Level 1)的 Web 服务引入了资源的概念。每一个资源有对应的标识符和表达。
  • 第三个层次(Level 2)的 Web 服务使用不一样的 HTTP 方法来进行不一样的操做,而且使用 HTTP 状态码来表示不一样的结果。如 HTTP GET 方法来获取资源,HTTP DELETE 方法来删除资源。
  • 第四个层次(Level 3)的 Web 服务使用 HATEOAS。在资源的表达中包含了连接信息。客户端能够根据连接来发现能够执行的动做。

从上述 REST 成熟度模型中能够看到,使用 HATEOAS 的 REST 服务是成熟度最高的,也是推荐的作法。对于不使用 HATEOAS 的 REST 服务,客户端和服务器的实现之间是紧密耦合的。客户端须要根据服务器提供的相关文档来了解所暴露的资源和对应的操做。当服务器发生了变化时,如修改了资源的 URI,客户端也须要进行相应的修改。而使用 HATEOAS 的 REST 服务中,客户端能够经过服务器提供的资源的表达来智能地发现能够执行的操做。当服务器发生了变化时,客户端并不须要作出修改,由于资源的 URI 和其余信息都是动态发现的。

因此咱们能够看到HATEOAS能够下降客户端和服务器之间的耦合。

咱们看看在Spring官网上的例子。

下面是一个类 Customer.

class Customer { String name; }

一个传统的例子是:

{ 
    "name" : "Alice" }

若是变成HATEOAS风格的,能够是下面这样:

{
    "name": "Alice", "links": [ { "rel": "self", "href": "http://localhost:8080/customer/1" } ] }

咱们能够看到,不只有了name,还多了一个links. links下的rel的值是self,意思就是说指向当前资源的连接。

关于ref的值,能够参考下表:

rel 属性值 描述
self 指向当前资源自己的连接的 rel 属性。每一个资源的表达中都应该包含此关系的连接。
edit 指向一个能够编辑当前资源的连接。
item 若是当前资源表示的是一个集合,则用来指向该集合中的单个资源。
collection 若是当前资源包含在某个集合中,则用来指向包含该资源的集合。
related 指向一个与当前资源相关的资源。
search 指向一个能够搜索当前资源及其相关资源的连接。
first、last、previous、next 这几个 rel 属性值都有集合中的遍历相关,分别用来指向集合中的第一个、最后一个、上一个和下一个资源。

 根据以上,咱们能够清楚的看出根据rel不一样的类型有不一样的用处,这样客户端能够智能的进行不一样的操做,达到解耦的目的。

OpenAPI

其实RESTful API都是和OpenAPI相关的,为何会把OpenAPI单独拿出来讲?原理很简单,那是由于如今不少API的定义,包括一些大厂的,都作的不是很好。RESTful API设计的最佳实践文档就在这里,可是大部分人仍是没有去遵照。关于RESTful API文档,建议去参考微软的文章(  https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design)。那么OpenAPI是干什么的?说白了就是为了RESTful API,定义了一个标准,让咱们和机器不用再去查看源代码、文档,甚至不用像我前面文件里抓包那样,去了解API的定义。 

最典型的例子仍是Swagger。Swagger的Editor等产品是支持OpenAPI的,总的来讲,Open API的那些标准不是太难,由于现成的例子供参考。关键是若是利用这些将本身的产品变得更加标准,这是很重要的策略和思路。我原来在这个上面花了不少时间引入到项目里,我以为是值的,一个是让产品规范了,有质的保证,二是让本身和同事的思惟提升了

 

总的来讲,这篇文章简单介绍了5G和HTTP的关系,以及HTTP里用到RESTful API,HTTP/2等技术,这和之前通讯领域是不同的。

参考文章:

相关文章
相关标签/搜索