基本概念
REST---REpresentational State Transfer 表现层状态转移
REST描述的是网络中client和server的一种交互形式,RESTful API是基于REST风格设计的网络接口。
全称其实是Resource Representational State Transfer:资源在网络中以某种表现形式进行状态转移,分解:
Resource:资源,即数据,是REST架构或者说整个网络处理的核心
Representational:某种表现形式,比如JSON,XML,JPEG等
State Transfer:状态变化,通过HTTP动词实现(GET---获取资源,POST---新建资源(也可以用于更新资源),PUT---更新资源,DELETE---删除资源)
Server提供的RESTful API中,URL只使用名词来指定资源,原则上不使用动词,且推荐用复数,比如:
api.qc.com/v1/news
获取新闻
api.qc.com/v1/friends
获取某人的好友列表
使用HTTP响应代码指示状态
十大HTTP响应状态代码的建议用法如下:
-
200 OK :通用成功状态代码。 这是最常见的代码。 用于表示成功。
-
201 CREATED :成功创建(通过POST或PUT)。 将Location header设置为包含指向新创建的资源的链接(在POST上)。 响应body 内容可能存在也可能不存在。
-
204 NO CONTENT :表示成功,但响应body中没有任何内容,通常用于DELETE和PUT操作。
-
400 BAD REQUEST :完成请求时的一般错误会导致无效状态。 例如域验证错误,缺少数据等。
-
401 UNAUTHORIZED :丢失或无效的身份验证令牌。
-
403 FORBIDDEN :当用户未被授权执行操作或资源由于某种原因(例如时间限 制等)不可用时的错误代码。
-
404 NOT FOUND :在找不到请求的资源时使用,不管是否不存在,或者是否是401或403,出于安全原因,服务需要屏蔽。
-
405 METHOD NOT ALLOWED :表示请求的URL存在,但请求的HTTP方法不对。 例如,POST /users/12345,其API不支持以这种方式创建资源(使用提供的ID)。 返回405时必须设置Allow header表明支持的HTTP方法。 例如:"Allow: GET, PUT, DELETE"
-
409 CONFLICT :请求导致资源冲突时。 重复条目,例如尝试创建具有相同信息的两个客户,以及在不支持级联删除时删除根对象。
-
500 INTERNAL SERVER ERROR :永远不要故意返回该状态码。 服务器端抛出异常时应使用catch-all捕捉。 仅将此用于客户端无法解决的错误(即服务器错误,client做啥也没有用,请联系后端人员解决)。
RESTful可以通过一套统一的接口为 Web,iOS和Android提供服务。另外对于广大平台来说,比如Facebook platform,微博开放平台,微信公共平台等,它们不需要有显式的前端,只需要一套提供服务的接口,于是RESTful更是它们最好的选择。
HATEOAS
HATEOAS-----Hypermedia as the engine of application state,超媒体是应用程序状态的引擎
通俗理解:遵循REST原则的API不要求客户端知道任何关于API结构的信息。相反,服务器需要提供客户端与服务交互所需的任何信息。HTML表单就是这样一个例子:服务器指定资源的位置和必需的字段。浏览器事先不知道在哪里提交信息,也不知道要提交什么信息。这两种形式的信息都完全由服务器提供。(这个原则被称为HATEOAS)
Richardson提出了一种REST成熟度模型Richardson Maturity Model(https://martinfowler.com/articles/richardsonMaturityModel.html),这种模式将REST按照成熟度划分为4个等级:
- Level0:使用HTTP作为WEB服务的传输方式,远程方法调用(RPC)的一种具体形式。
- Level1:使用适当的URL(使用名字)公开资源,这种方式提出了资源的概念
- Level2:资源使用正确的URL+HTTP方法,比如更新用户就用PUT方式,查询用GET方式
- Level3:使用HATEOAS,在资源的表达中包含了链接信息,客户端可以在链接信息中发现可以执行的操作
HATEOAS约束是REST风格中成熟度最高的,也是官方推荐的一种方式。没使用HATEOAS的项目,服务端和客户端是耦合的,客户端只能通过相关文档来知道服务端做了什么修改,使用HATEOAS约束的REST服务,服务端修改接口信息后,客户端可以通过服务器提供的资源的表达来智能地发现可以执行的操作,客户端不需要做啥修改,因为资源信息是会动态改变的。Spring HATEOAS官网参考链接:https://spring.io/projects/spring-hateoas
微服务相关组件
Spring Boot擅长的是集成,Spring Cloud基于Spring Boot开发,是一系列微服务框架的一站式技术解决方案。它包括服务注册中心、负载均衡(指代下图中的远程服务调用基础)、熔断限流、服务通信、网关、配置中心、消息总线和集群状态等功能,各公共服务组件变迁如下图所示。(图中绿色代表目前建议使用的组件,红色组件面临着淘汰与替换)
[图片上传失败...(image-be9fa3-1665713225526)]
很多厂商基于Spring Cloud设计理念,开发自己的微服务一站式解决方案,比较著名的是阿里的Spring Cloud Alibaba和携程的apollo。
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(分区容错性)。由于分区容错性是在分布式系统中必须要保证的,因此我们需要在A和C之间进行权衡。Zookeeper保证的是CP,而Eureka保证的是AP。
[图片上传失败...(image-f1ebad-1665713225526)]
微服务中的远程调用
远程调用一般会分为以下两种:
一、基于HTTP的Restful形式的广义远程调用
以Spring Boot的Feign和RestTemplate为代表,采用的协议是Http的7层调用协议,并且协议的参数和响应序列化以JSON格式和XML格式为主。
优势:对服务的提供和调用方法没有任何技术限定,自由灵活,更符合微服务理念。
劣势:消息封装臃肿。
常用的有:Web接口、RestTemplate+Okhttp
- Http接口()
- Feign
- RPC(Remote Produce Call,远程过程调用)(Dubbo、Socket编程)
- Webservice
二、RPC架构
远程过程调用(Remote Procedure Call,RPC),RPC是一个概念。在今天,RPC已经不仅仅是远程,这个远程,确切来说,就是指不在一个进程内,只能通过其他协议来完成,通常都是TCP或者是HTTP。RPC可以基于HTTP协议(feign)、TCP协议(Netty)、RMI协议(soap)和web服务(XML-RPC)框架实现。
RPC的实现过程:客户端通过上述协议向服务器发送接口、参数、参数类型、方法、返回值、返回值类型等(称为方法签名),通知服务器要调用的接口方法。在传输过程中,客户端调用的接口信息会以序列化的方式发送到服务器端,由于序列化方法的不同,也出现了一些框架和协议,如Dubbo中的Dubbo协议、gRPC中的 protobuf序列化协议等。实际上,它们都是基于远程调用的概念。
- 序列化框架包括:Hession、Protobuf、Kryo等,不同的序列化框架性能不一,序列化后的字节码越小,占用的带宽越小,序列化时间越长,线程IO延迟越短。
一个完整的RPC架构包含以下四个核心组件: - 客户端(Client):服务的调用方
- 服务端(Server):服务的提供者
- 客户端存根(Client Stub):存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
- 服务端存根(Server Stub):接收客户端发送过来的消息,将消息解包,并调用本地的方法。
[图片上传失败...(image-3ca54c-1665713225526)]
什么时候需要RPC
由于HTTP的三次握手协议限制,每发送一次请求,都会有一次建立连接的过程,会带来一定的延迟,此外i,HTTP报文以及JSON的庞大也需要做一些优化。可以从:减少传输量、简化协议、用长连接(不用每个请求都走三次握手流程)等方面进行优化。因此,在高性能要求下,HTTP协议不适合用做线上分布式服务之间使用的通信协议。
RPC服务和HTTP服务还是存在很多的不同点的,一般来说,RPC服务主要是针对大型企业的,而HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。
RPC VS. HTTP
RPC | REST | |
---|---|---|
耦合性 | 强耦合 | 松耦合 |
消息协议 | binary、Protobuf、Thrift | 文本、xml、json |
通信协议 | TCP | HTTP |
接口契约IDL | Protobuf、Thrift | Swagger |
开发调试 | 消息不可读 | 可读、可调试 |
对外开放 | 一般作为内部各个系统的通信框架 | 对接外部系统 |
网友评论