详解SpringCloud-OpenFeign组件的使用

思考: 使用RestTemplate+ribbon已经可以完成服务间的调用,为什么还要使用feign?

String restTemplateForObject = restTemplate.getForObject("http://服务名/url?参数" + name, String.class);

存在问题:

1.每次调用服务都需要写这些代码,存在大量的代码冗余

2.服务地址如果修改,维护成本增高

3.使用时不够灵活

说明

https://cloud.spring.io/spring-cloud-openfeign/reference/html/

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性(可以使用springmvc的注解),可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,默认实现了负载均衡的效果并且springcloud为feign添加了springmvc注解的支持。

1.openFeign 服务调用

还是在上一个项目的基础之上,在users项目中

1.服务调用方法引入依赖OpenFeign依赖

<!--Open Feign依赖-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.入口类加入注解开启OpenFeign支持

@SpringBootApplication
@EnableFeignClients //开启openfeign支持
public class Users9999Application {
 public static void main(String[] args) {
  SpringApplication.run(Users9999Application.class, args);
 }
}

3.创建一个客户端调用接口

// 此时的product项目中的方法
@RestController
@Slf4j
public class ProductController {

 @Value("${server.port}")
 private int port;

 @GetMapping("/product/findAll")
 public Map<String, Object> findAll(){
  log.info("商品服务调用成功,当前的服务端口:[{}]",port);
  HashMap<String, Object> map = new HashMap<>();
  map.put("msg","服务调用成功,服务提供的端口为:"+port);
  map.put("status",true);
  return map;
 }
}

//--------------------------------------------------------------------
package com.md.clients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author md
 * @Desc 调用商品服务的组件
 * @date 2020/12/9 15:30
 */

// 指定当前的接口是openfeign组件,value是调用的服务名
@FeignClient("products")
public interface ProductClient {

 @GetMapping("/product/findAll")
 String findAll();
}

4.使用feignClient客户端对象调用服务

@RestController
@Slf4j
public class UserController {

	//注入客户端对象
	@Autowired
	private ProductClient productClient;

	@GetMapping("/user/findAllFeignClient")
	public String findAllFeignClient(){
 		log.info("通过使用OpenFeign组件调用商品服务...");
 		String msg = productClient.findAll();
 		return msg;
	}
}

5.访问并测试服务http://localhost:9999/user/findAllFeignClient

2.调用服务并传参

服务和服务之间通信,不仅仅是调用,往往在调用过程中还伴随着参数传递,接下来重点来看看OpenFeign在调用服务时如何传递参数

3.GET方式调用服务传递参数

  • 在商品服务中加入需要传递参数的服务方法来进行测试
  • 在用户服务中进行调用商品服务中需要传递参数的服务方法进行测试

1.商品服务中添加如下方法

 @GetMapping("/product/findOne")
public Map<String,Object> findOne(String productId){
 log.info("商品服务查询商品信息调用成功,当前服务端口:[{}]",port);
 log.info("当前接收商品信息的id:[{}]",productId);
 Map<String, Object> map = new HashMap<String,Object>();
 map.put("msg","商品服务查询商品信息调用成功,当前服务端口: "+port);
 map.put("status",true);
 map.put("productId",productId);
 return map;
}

2.用户服务中在product客户端中声明方法

//
@FeignClient("products")
public interface ProductClient {
	@GetMapping("/product/findOne")
 	 Map<String, Object> findOne(@RequestParam("productId") String productId);
}

注意:使用openfeign的get方式传递参数,参数变量必须通过@RequestParam注解进行修饰

3.用户服务中调用并传递参数

//
//注入客户端对象
@RestController
@Slf4j
public class UserController {	

 @Autowired
 private ProductClient productClient;

  @GetMapping("/user/findOne")
  public Map<String, Object> findOne(String productId){
   log.info("用来测试Openfiegn的GET方式参数传递");
   Map<String, Object> msg = productClient.findOne(productId);
   log.info("调用返回信息:[{}]",msg);
   return msg;
  }
}

4.测试访问

4.post方式调用服务传递参数

  • 在商品服务中加入需要传递参数的服务方法来进行测试
  • 在用户服务中进行调用商品服务中需要传递参数的服务方法进行测试

1.商品服务加入post方式请求并接受name

@PostMapping("/product/save")
public Map<String,Object> save(String name){
 log.info("商品服务保存商品调用成功,当前服务端口:[{}]",port);
 log.info("当前接收商品名称:[{}]",name);
 Map<String, Object> map = new HashMap<String,Object>();
 map.put("msg","商品查询服务完成当前服务端口: "+port);
 map.put("status",true);
 map.put("name",name);
 return map;
}

2.用户服务中在product客户端中声明方法

//value属性用来指定:调用服务名称
@FeignClient("products")
public interface ProductClient {
 @PostMapping("/product/save")
 String save(@RequestParam("name") String name);
}

3.用户服务中调用并传递参数

@Autowired
private ProductClient productClient;

@PostMapping("/user/save")
public Map<String, Object> save(String productName){
 log.info("接收到的商品信息名称:[{}]",productName);
 Map<String, Object> map = productClient.save(productName);
 log.info("调用成功返回结果: "+map);
 return map;
}

4.测试访问

5.传递对象类型参数

  • 商品服务定义对象
  • 商品服务定义对象接收方法
  • 用户服务调用商品服务定义对象参数方法进行参数传递
//1.商品服务定义对象
@Data
public class Product {
 private Integer id;
 private String name;
 private Date bir;
}
//2.商品服务定义接收对象的方法
@PostMapping("/product/saveProduct")
public Map<String,Object> saveProduct(@RequestBody Product product){
 log.info("商品服务保存商品信息调用成功,当前服务端口:[{}]",port);
 log.info("当前接收商品名称:[{}]",product);
 Map<String, Object> map = new HashMap<String,Object>();
 map.put("msg","商品服务查询商品信息调用成功,当前服务端口: "+port);
 map.put("status",true);
 map.put("product",product);
 return map;
}
//3.将商品对象复制到用户服务中
// 先阶段先这样用着

//4.用户服务中在product客户端中声明方法
@FeignClient("products")
public interface ProductClient {
 @PostMapping("/product/saveProduct")
 String saveProduct(@RequestBody Product product);
}
//注意:服务提供方和调用方一定要加入@RequestBody注解 

注意:服务提供方和调用方一定要加入@RequestBody注解

// 5.在用户服务中调用保存商品信息服务
//注入客户端对象
@Autowired
private ProductClient productClient;

	@PostMapping("/user/saveProduct")
 public Map<String, Object> saveProduct(Product product){
  log.info("接收到的商品信息:[{}]",product);
  Map<String, Object> map = productClient.saveProduct(product);
  log.info("调用成功返回结果: "+map);
  return map;
 }

测试

5.OpenFeign超时设置

1.超时说明默认情况下,openFiegn在进行服务调用时,要求服务提供方处理业务逻辑时间必须在1S内返回,如果超过1S没有返回则OpenFeign会直接报错,不会等待服务执行,但是往往在处理复杂业务逻辑是可能会超过1S,因此需要修改OpenFeign的默认服务调用超时时间。

2.模拟超时服务提供方加入线程等待阻塞

3.进行客户端调用

4.修改OpenFeign默认超时时间

# 这里的PRODUCTS使用的是大写的方法
feign.client.config.PRODUCTS.connectTimeout=5000 #配置指定服务连接超时
feign.client.config.PRODUCTS.readTimeout=5000		 #配置指定服务等待超时
#feign.client.config.default.connectTimeout=5000 #配置所有服务连接超时
#feign.client.config.default.readTimeout=5000			#配置所有服务等待超时

6.OpenFeign调用详细日志展示

0.说明

  • 往往在服务调用时我们需要详细展示feign的日志,默认feign在调用是并不是最详细日志输出,因此在调试程序时应该开启feign的详细日志展示。feign对日志的处理非常灵活可为每个feign客户端指定日志记录策略,每个客户端都会创建一个logger默认情况下logger的名称是feign的全限定名需要注意的是,feign日志的打印只会DEBUG级别做出响应。
  • 我们可以为feign客户端配置各自的logger.level对象,告诉feign记录那些日志logger.lever有以下的几种值
  • NONE 不记录任何日志 BASIC 仅仅记录请求方法,url,响应状态代码及执行时间
  • HEADERS 记录Basic级别的基础上,记录请求和响应的header FULL 记录请求和响应的header,body和元数据

1.开启日志展示

# 这里的PRODUCTS使用的是大写的方法
feign.client.config.PRODUCTS.loggerLevel=full #开启指定服务日志展示
#feign.client.config.default.loggerLevel=full #全局开启服务日志展示
logging.level.com.baizhi.feignclients=debug #指定feign调用客户端对象所在包,必须是debug级别

2.测试服务调用查看日志

到此这篇关于SpringCloud-OpenFeign组件的使用的文章就介绍到这了,更多相关SpringCloud-OpenFeign组件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud Feign的使用简介

    简介 feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service.Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端. 在springcloud中不仅可以使用Ribbo进行负载均衡,也可以使用Feign.Feign是在Ribbon的基础上进行了一次改进,采用接口的方式实现负载均衡. 使用 导入依赖 <dependency> <groupId>org.sprin

  • 完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题

    事发地 原默认的Feign是使用URLConnector进行通信的,当换为okhttp时,直接引入包及配置以下内容根本不生效,还是走原生的. feign: okhttp: enable: true 事件还原 创建项目并引入pom相关的依赖如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xml

  • SpringCloud Feign如何在远程调用中传输文件

    1. 文件远程传输主要涉及3点: 请求方式, 媒体类型, 序列化与反序列化, 把握住了这3点,基本上就可以搞 2. 使用Feign传输,首先搭建起Feign的架子 2.1 引入spring-cloud-starter-eureka-server依赖,用于启动一个eureka注册中心 2.2 引入spring-cloud-starter-eureka依赖,用于开启向eureka注册中心注册自己 2.3 在调用远程服务的客户端引入spring-cloud-starter-feign, 用于使用fei

  • SpringCloud Open feign 使用okhttp 优化详解

    我就废话不多说了,大家还是直接看代码吧~ <!--web 模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!--排除tomcat依赖 --> <exclusion> <artifactId&

  • SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法

    1.Ribbon Spring Cloud Ribbon是基于Netflix Ribbon实现的-套客户端―负载均衡的工具. 简单的说,Ribbon是Netlix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用.Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等.简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器.我们很容易使用Ribbon实现自定义的负载均

  • SpringCloud之Feign远程接口映射的实现

    一.简介 SpringCloud是基于Restful的远程调用框架,引入Ribbon负载均衡组件后还需要客户端使用RestTemplate调用远程接口,操作起来还显得繁琐.SpringCloud提供了远程接口映射,将远程Restful服务映射为远程接口,消费端注入远程接口即可实现方法调用. 二.流程 1.新建远程接口映射模块service-api,并引入Feign接口映射依赖 <dependencies> <dependency> <groupId>org.spring

  • SpringCloud OpenFeign Post请求400错误解决方案

    在微服务开发中SpringCloud全家桶集成了OpenFeign用于服务调用,SpringCloud的OpenFeign使用SpringMVCContract来解析OpenFeign的接口定义. 但是SpringMVCContract的Post接口解析实现有个巨坑,就是如果使用的是@RequestParam传参的Post请求,参数是直接挂在URL上的. 问题发现与分析 最近线上服务器突然经常性出现CPU高负载的预警,经过排查发现日志出来了大量的OpenFeign跨服务调用出现400的错误(HT

  • 浅谈SpringCloud feign的http请求组件优化方案

    1 描述 如果我们直接使用SpringCloud Feign进行服务间调用的时候,http组件使用的是JDK的HttpURLConnection,每次请求都会新建一个连接,没有使用线程池复用.具体的可以从源码进行分析 2 源码分析 我们在分析源码很难找到入口,不知道从何开始入手,我们在分析SpringCloud feign的时候可用在配置文件下面我讲一下个人的思路. 1 首先我点击@EnableFeignClients 看一下这个注解在哪个资源路径下 如下图所示: 2 找到服务启动加载的配置文件

  • SpringCloud Feign转发请求头(防止session失效)的解决方案

    微服务开发中经常有这样的需求,公司自定义了通用的请求头,需要在微服务的调用链中转发,比如在请求头中加入了token,或者某个自定义的信息uniqueId,总之就是自定义的一个键值对的东东,A服务调用B服务,B服务调用C服务,这样通用的东西如何让他在一个调用链中不断地传递下去呢?以A服务为例: 方案1 最傻的办法,在程序中获取,调用B的时候再转发,怎么获取在Controller中国通过注解获取,或者通过request对象获取,这个不难,在请求B服务的时候,通过注解将值放进去即可:简代码如下: 获取

  • 基于springcloud异步线程池、高并发请求feign的解决方案

    ScenTaskTestApplication.java package com.test; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; /** * @author scen *

随机推荐