微服务服务间调用方式

目录

1 RPC和HTTP

1.1 RPC是什么

1.2 RPC的主要实现

1.3 RPC的网络通讯协议

1.4 RPC的数据传输格式

1.5 RPC框架有哪些

1.6 RPC调用过程示意图

1.7 Http是什么

1.8 RPC框架有哪些

1.9 Http调用过程示意图

1.10 RPC和Http的相同点和不同点

1.11 RPC和Http对比

1.12 使用场景:

2 OpenFeign

2.1 什么是Feign

2.2 什么是OpenFeign

2.3 常用注解

2.4 Feign和OpenFeign的相同点

2.5 Feign和OpenFeign的区别

2.6 OpenFeign超时处理

2.7 OpenFeign日志增强

2.8 小结

3 RestTemplate

3.1 GET请求

getForEntity

getForObject

3.2 POST请求

postForEntity

postForObject

postForLocation

3.3 put请求

3.4 delete请求

3.5 通用方法exchange

3.6 总结

RestTemplate和OpenFeign的区别:


1 RPC和HTTP

1.1 RPC是什么

RPC:Remote Procedure Call(远程过程调用) 是一个计算机通信协议,这个协议允许运行于一台计算机的程序调用另一台计算机的子程序,程序员不用再为这个交互编写程序;

类似的是RMI(Remote Methods Invoke 远程方法调用)

1.2 RPC的主要实现

  1. 实现远程调用其他服务;
  2. 像调用本地服务一样去调用远程的服务;

RPC强调的是过程调用,调用的过程对用户而言是应该是透明的,用户不用去关心调用的细节,可以像调用本地服务一样调用远程服务;所以RPC一定要对调用的过程进行封装

1.3 RPC的网络通讯协议

RPC采用的是TCP作为底层的传输协议

1.4 RPC的数据传输格式

两个程序间进行通讯,必须要约定好数据传输格式,必须定义好请求和响应的格式

数据在网络中传输需要进行序列化,所以需要约定统一的序列化方式

1.5 RPC框架有哪些

RPC框架有:dubbo、webservice(cxf)、hessian(RMI远程方法调用,比较轻量)

1.6 RPC调用过程示意图

微服务服务间调用方式_第1张图片

1.7 Http是什么

http其实是一种网络传输协议,基于TCP,规定了数据传输的格式,现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。

1.8 RPC框架有哪些

http框架有:httpClient

1.9 Http调用过程示意图

微服务服务间调用方式_第2张图片

1.10 RPC和Http的相同点和不同点

相同点

底层通讯都是基于socket,都可以实现远程调用,都可以实现服务间调用;

不同点:

  1. RPC是跨操作系统在同一编程语言内使用;Http是跨操作系统跨编程语言的远程调用框架
  2. 当使用RPC框时限为服务调用的时候,要求服务提供方和服务消费方都必须使用统一的RPC框架,要么都是dubbo,要么都是cxf;当使用http进行服务间调用的时候,无需关注服务提供方使用的编程语言,也无需关注服务消费方使用的编程语言,服务提供方只需要提供restful风格的接口,服务消费方,按照restful的原则,请求服务即可;
  3. RPC调用快、处理快;Http通用性强;
  4. Hessian只支持Post请求,只支持Java语言
  5. RPC需要满足像调用本地服务一样调用远程服务,也就是对调用过程在API层面进行封装;Http协议没有这样的要求,因此请求、响应等细节需要我们自己去实现。

1.11 RPC和Http对比

  • RPC要比http更快,虽然底层都是socket,但是http协议的信息往往比较臃肿
  • RPC实现较为复杂,http相对比较简单
  • http更胜一筹,因为它不关心实现细节,跨平台、跨语言。

1.12 使用场景:

效率要求高,开发过程使用统一,可以使用RPC;

需要灵活,跨语言、跨平台,可以使用Http

一般来讲,微服务强调的是独立、自治、灵活。而RPC方式的限制较多,因此微服务框架中,一般都会采用基于Http的Rest风格服务。

2 OpenFeign

2.1 什么是Feign

Netflix Feign 是 Netflix 公司发布的一种实现负载均衡和服务调用的开源组件。Spring Cloud 将其与 Netflix 中的其他开源服务组件(例如 Eureka、Ribbon 以及 Hystrix 等)一起整合进 Spring Cloud Netflix 模块中,整合后全称为 Spring Cloud Netflix FeignFeign 对 Ribbon 进行了集成,利用 Ribbon 维护了一份可用服务清单,并通过 Ribbon 实现了客户端的负载均衡。

Feign 是一种声明式服务调用组件,它在 RestTemplate 的基础上做了进一步的封装。通过 Feign,我们只需要声明一个接口并通过注解进行简单的配置(类似于 Dao 接口上面的 Mapper 注解一样)即可实现对 HTTP 接口的绑定。通过 Feign,我们可以像调用本地方法一样来调用远程服务,而完全感觉不到这是在进行远程调用。

Feign 支持多种注解,例如 Feign 自带的注解以及 JAX-RS 注解等,但遗憾的是 Feign 本身并不支持 Spring MVC 注解,这无疑会给广大 Spring 用户带来不便。

2.2 什么是OpenFeign

2019 年 Netflix 公司宣布 Feign 组件正式进入停更维护状态,于是 Spring 官方便推出了一个名为 OpenFeign 的组件作为 Feign 的替代方案。

OpenFeign 全称 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用与负载均衡组件,它的出现就是为了替代进入停更维护状态的 Feign。

OpenFeign 是 Spring Cloud 对 Feign 的二次封装,它具有 Feign 的所有功能,并在 Feign 的基础上增加了对 Spring MVC 注解的支持,例如 @RequestMapping、@GetMapping 和 @PostMapping 等。

2.3 常用注解

注解 说明
@FeignClient 该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。
@EnableFeignClients 该注解用于开启 OpenFeign 功能,当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。
@RequestMapping Spring MVC 注解,在 Spring MVC 中使用该注解映射请求,通过它来指定控制器(Controller)可以处理哪些 URL 请求,相当于 Servlet 中 web.xml 的配置。
@GetMapping Spring MVC 注解,用来映射 GET 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.GET) 。
@PostMapping Spring MVC 注解,用来映射 POST 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.POST) 。

2.4 Feign和OpenFeign的相同点

  1. Feign 和 OpenFeign 都是 Spring Cloud 下的远程调用和负载均衡组件。

  2. Feign 和 OpenFeign 作用一样,都可以实现服务的远程调用和负载均衡。

  3. Feign 和 OpenFeign 都对 Ribbon 进行了集成,都利用 Ribbon 维护了可用服务清单,并通过 Ribbon 实现了客户端的负载均衡。

  4. Feign 和 OpenFeign 都是在服务消费者(客户端)定义服务绑定接口并通过注解的方式进行配置,以实现远程服务的调用。

2.5 Feign和OpenFeign的区别

官方已经宣布停止更新Feign组件,所以可以使用OpenFeign进行代替

Feign OpenFeign
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务,Feign的使用方式是:使用Feign的注解定义接口,调用这个接口就可以调用服务注册中心的服务 OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。 OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务

Feign本身不支持SpringMVC的注解,它有一套自己的注解;

调用方式是通过@RequestLine指定HTTP协议及URL地址

微服务服务间调用方式_第3张图片

2.6 OpenFeign超时处理

OpenFeign客户端的默认超时时间为1秒钟,如果服务端处理请求的时间超过1秒就会报错(在一秒内不能请求到结果就会返回请求超时的错误)。可以通过在yml中假如以下内容进行配置

ribbon:
  ReadTimeout: 6000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
  ConnectionTimeout: 6000 #建立连接后,服务器读取到可用资源的时间
​
feign:
  client:
     httpclient:
       enabled: true # 开启 HttpClient优化连接池
  compression:
     request:
       enabled: true # 开启请求数据的压缩功能
       mime-types: text/xml,application/xml, application/json # 压缩类型
       min-request-size: 1024 # 最小压缩值标准,当数据大于 1024 才会进行压缩
     response:
       enabled: true # 开启响应数据压缩功能

2.7 OpenFeign日志增强

yml添加日志级别声明

logging:
    level:
        com.xxx.xxx.xxxService:debug    #feign日志以什么样的级别监控该接口

com.xxx.xxx.xxxService是开启@FeignClient注解的接口(即服务绑定接口)的完整类名。也可以只配置部分路径,表示监控该路径下的所有服务绑定接口

debug表示监听该接口的日志级别

//创建日志配置类
@Configuration
public class ConfigBean {
​
  /**
    * OpenFeign 日志增强
    * 配置 OpenFeign 记录哪些内容
    */
  @Bean
  Logger.Level feginLoggerLevel() {
      return Logger.Level.FULL;
  }
}

这个配置的作用是通过配置的logger.level对象告诉OpenFeign记录哪些日志内容。logger.level的具体级别如下:

NONE:不记录任何信息。

BASIC:仅记录请求方法、URL以及响应状态码和执行时间。

HEADERS:除了记录BASIC级别的信息外,还会记录请求和响应的头信息。

FULL:记录所有请求与响应的明细,包括头信息,请求体,元数据等等。

FULL级别如图:

微服务服务间调用方式_第4张图片

2.8 小结

OpenFeign本质就是通过接口+注解实现对服务提供者的绑定,从而轻松实现服务之间的调用。OpenFeign的功能比较齐全;编写接口将远程调用的同一个微服务的API集中,可以很方便的管理API;

3 RestTemplate

RestTemplate是从Spring3.0开始支持的一个HTTP请求工具,他提供了常见的REST请求方案的模板,例如GET请求、POST请求、PUT请求、DELETE请求以及一些通用的请求执行方法exchange以及execute。RestTemplate继承自InterceptingHttpAccessor并且实现了RespOperations接口,其中RestOperations接口定义了基本的RESTful操作,这些操作在RestTemplate中都得到了实现。

3.1 GET请求

在RestTemplate中GET请求有这几个方法:

微服务服务间调用方式_第5张图片

这些请求中有两类方法,分别是getForObject和getForEntity,每一个类都有三个重载方法。

getForEntity

getForEntity(String url, Class , Object... )方法,第一个参数是url,url中有一个占位符{1},如果有多个占位符分别用{2}、{3}...去表示,第二个参数是接口返回的数据类型,最后一个是可变长度的参数,用来给占位符填值的。在返回的ResponseEntity中,可以获取响应头中的信息,其中getStatusCode方法用来获取响应状态码,getBody方法用来获取响应数据,getHeaders方法用来获取响应头;

除了这一种方法外,还有两种方法也就是getForEntity的两位两个重载方法,使用map

Map map = new HashMap<>();
map.put("name",name);
ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class, map);

还有一种就是使用url对象

String url = "http://" + host + ":" + port + "/hello?name=" + URLEncoder.encode(name, "UTF-8");
URI uri = URI.create(url);
ResponseEntity responseEntity = restTemplate.getForEntity(uri,String.class);

注意这里使用URL如果是带了中文字符串,那么就需要使用UTF-8

getForObject

getForObject 方法和 getForEntity 方法类似,getForObject 方法也有三个重载的方法,参数和 getForEntity 一样。

getForObject 和 getForEntity 的差异主要体现在返回值的差异上, getForObject 的返回值就是服务提供者返回的数据,使用 getForObject 无法获取到响应头。

例如,还是上面的请求,利用 getForObject 来发送 HTTP 请求,结果如下:

String url = "http://" + host + ":" + port + "/hello?name=" + URLEncoder.encode(name, "UTF-8");
URI uri = URI.create(url);
String s = restTemplate.getForObject(uri, String.class);

注意,这里返回的 s 就是 provider 的返回值,如果开发者只关心 provider 的返回值,并不关系 HTTP 请求的响应头,那么可以使用该方法。

3.2 POST请求

在RestTemplate中POST请求有这几个方法:

微服务服务间调用方式_第6张图片

post 请求的方法类型除了 postForEntity 和 postForObject 之外,还有一个 postForLocation。这里的方法类型虽然有三种,但是这三种方法重载的参数基本是一样的。

postForEntity

在Post请求中,参数的传递可以是key/value的形式,也可以是JSON数据、

postForObject

postForObject和postforEntity基本一致,就是返回类型不同、

postForLocation

postForLocation方法的返回值是一个Url对象,因为POST请求一般用来添加数据,有的时候需要将刚刚添加成功的数据的url返回来,此时就可以使用这个方法,

注意:postForLocation方法返回的Url实际上是响应头的location字段,所以,provider中register接口的响应头必须要有location字段(即请求的接口是一个重定向的接口),否则PSOTForLocation方法的返回值就为null。

3.3 put请求

put请求的方法有三个

这三个重载的方法的参数和POST是一样对的,可以用key/value的形式传参,也可以用json的形式传参,无论哪种方式,都是没有返回值的。

3.4 delete请求

delete请求方法有三个

不同于POST和PUT ,DELETE请求的参数只能在地址栏传送,可以是直接放在路径中,也可以用 key/value 的形式传递,当然,这里也是没有返回值的。

3.5 通用方法exchange

在RestTemplate中还有一个通用的方法exchange。为什么说它通用呢?因为这个方法需要你在调用的时候去指定请求类型,即它既能做GET请求,也能做POST请求,也能做其它各种类型的请求。如果需要对请求进行封装,使用它再合适不过了。

3.6 总结

RestTemplate这个调用方式存在以下问题:

  • 代码可读性差,编码体验不统一

  • 参数负责URL难以维护

  • 同一个服务提供者的名称可能分布在不同的controller里,或者一个controller中有几个不同的微服务提供者,这会比较难去管理。

RestTemplate和OpenFeign的区别

请求方式不一样

RestTemplate需要每个请求都拼接url+参数+类文件,灵活性高但是消息封装臃肿。

feign可以伪装成类似SpringMVC的controller一样,将rest的请求进行隐藏,不用再自己拼接url和参数,可以便捷优雅地调用HTTP API。

底层实现方式不一样

RestTemplate在拼接url的时候,可以直接指定ip地址+端口号,不需要经过服务注册中心就可以直接请求接口;也可以指定服务名,请求先到服务注册中心(如nacos)获取对应服务的ip地址+端口号,然后经过HTTP转发请求到对应的服务接口(注意:这时候的restTemplate需要添加@LoadBalanced注解,进行负载均衡)。

Feign的底层实现是动态代理,如果对某个接口进行了@FeignClient注解的声明,Feign就会针对这个接口创建一个动态代理的对象,在调用这个接口的时候,其实就是调用这个接口的代理对象,代理对象根据@FeignClient注解中name的值在服务注册中心找到对应的服务,然后再根据@RequestMapping等其他注解的映射路径构造出请求的地址,针对这个地址,再从本地实现HTTP的远程调用。

本文是自己学习记录文章,可能有多处资料,如有侵权,请告知删除,也会更新一些关于本技术的新学习内容

转载地址:Feign与OpenFeign · 语雀       ​远程调用方式 RPC 和 Http

你可能感兴趣的:(java,spring,cloud,微服务,spring,boot,spring)