DuckBlog

Duck Blog

唐如飞

( ^∀^)/欢迎\( ^∀^)

79 文章数
14 评论数

Feign

tangrufei
2022-08-29 / 0 评论 / 283 阅读 / 0 点赞

1、客户端负载均衡 - Feign

1.1、什么是Feign

1、Ribbon有什么问题?

前面的可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻不高级不优雅

2、什么是Feign

Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),feign内部也使用了ribbon做负载均衡,可以让我们不再需要显式地使用这两个组件。

1.2、实战编码案例:

我们这里想要实现的效果和之前学习Ribbon案例的效果一样:

image-20210901183153612

为了不和前面的案例混淆代码,我们搭建新工程“支付服务”来演示Feign。那在这里支付服务和订单服务充当的角色一样,都是服务消费者,通过调用用户服务来获取数据。

那么支付服务需要做什么事情?思路如下:

  1. 搭建基础项目结构

  2. 注册到Eureka

  3. 集成Feign向用户服务发起调用

1.3、搭建新的支付服务注册到Eureka服务端

1、创建工程

创建工程 springcloud-pay-server-1040,用来集成Feign,那么目前项目结构如下:

springcloud-parent
springcloud-eureka-server-1010
springcloud-order-server-1030
springcloud-pay-server-1040 //支付服务用来集成Feign
springcloud-user-common
springcloud-user-server-1020
pom.xml

2、导入依赖

这里先不集成Feign,先其他基础包注册到Eureka服务端,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <artifactId>springcloud-parent</artifactId>
       <groupId>cn.itsource</groupId>
       <version>1.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>

   <artifactId>springcloud-pay-server-1040</artifactId>

   <dependencies>
       <dependency>
           <!--1、引入Eureka客户端依赖-->
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
       </dependency>

       <!--必须引入web基础依赖,相当于引入了tomcat-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
           <groupId>cn.itsource</groupId>
           <artifactId>springcloud-user-common</artifactId>
           <version>1.0-SNAPSHOT</version>
       </dependency>

   </dependencies>

</project>

3、配置启动类

/**
* @description: 支付服务启动类
*/
@SpringBootApplication
@EnableEurekaClient
public class PayServerApplication1040 {

   public static void main(String[] args) {
       SpringApplication.run(PayServerApplication1040.class);
  }
}

4、配置文件application.yml

eureka:
client:
  serviceUrl: #指向Eureka服务端地址
    defaultZone: http://admin:123456@peer1:1010/eureka/,http://admin:123456@peer2:1011/eureka/,http://admin:123456@peer3:1012/eureka/
instance:
  prefer-ip-address: true #开启用IP注册
  instance-id: pay-server:1040 #自定义实例ID
server:
port: 1040

spring:
application:
  name: pay-server #服务名

OK了,此时运行Eureka服务端(我这里只运行1010这一台),然后运行支付服务,浏览器访问:http://localhost:1010,可以看到支付服务已经可以显示了,说明支付服务已经成功注册到Eureka服务端了,接下来就可以集成Feign了

1.4、集成Feign

1、加入依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、开启Feign支持

启动类添加@EnableFeignClients标签:

image-20210817165737488

3、编写Feign客户端接口

@FeignClient("user-server")
public interface UserFeignClient {

   @GetMapping(value = "/user/{id}")
   User getUserById(@PathVariable("id")Long id);
}
  • 解释

UserFeignClient : 这个接口就是用来调用 user-server这个服务的Feign的客户端接口 @FeignClient("user-server") : user-server是服务的名字,我们要调用户服务,feign根据服务名能够找到 目标服务 ,根据方法上的 GetMapping的值可以找到目标服务的controller的方法

  • 千万注意:

1.服务名一定不要写错 2.@GetMapping一定要和目标服务的controller的方法的GetMapping一样 3.方法的参数一定要和目标服务的controller的方法的参数一样 4.方法的返回值一定要和目标服务的controller的方法的返回值一样

  • 建议

服务名直接去目标服务配置中拷贝

方法直接从目标服务controller中拷贝

4、Feign和openFeign区别

Feign:

  • Feign是Spring Cloud组件中的一个轻量级RESTfulHTTP服务客户端

  • Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务

  • Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务

  • 注意:Feign本身不支持Spring MVC的注解,它有一套自己的注解

openFeign:

  • OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等

  • OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务

5、编写Controller

通过注入UserFeignClient ,直接发起调用:

/**
* @description: 支付服务API
*/
@RestController
public class PayController {

   @Autowired
   private UserFeignClient userFeignClient;

   //浏览器来调用此接口
   @RequestMapping("/pay/{id}")
   public User getUserById(@PathVariable("id")Long id){
       //使用Feign调用用户服务获取User
       return userFeignClient.getUserById(id);
  }
}

6、测试

启动Eureka服务端,启动用户服务,启动支付服务,然后通过浏览器访问pay-server的controller,浏览器输入:http://localhost:1050/pay/11,效果如下:

image-20210817165251891

1.5、Feign工作原理(重点)

  1. 要使用Feign,我们除了导入依赖之外,需要主配置类通过@EnableFeignClients(value="")注解开启Feign,触发程序扫描 classPath中所有被@FeignClient注解的修饰类。

  2. 同时我们需要为Feign编写客户端接口,接口上需要写上@FeignClient注解。

  3. 当程序启动,含有@FeignClient注解的所有接口,都会被扫描到然后交给Spring管理,使用JDK动态代理为其生成一个代理对象,本质上是该代理对象注册到Spring容器中。

  4. 当请求到来时,调用接口实际上就是在调用代理对象,此时,所有请求都会被转交给Feign框架,Feign会为每个方法生成一个RequestTemplate,并封装好url,请求参数等信息,以 HTTP 的形式发送出去,生成request请求,交给Http客户端(UrlConnection ,HttpClient,OkHttp)

  5. Http客户端会交给LoadBalancerClient,使用Ribbon的负载均衡发起调用

1.6、Feign参数配置

1、负载均衡配置

Feign已经集成了Ribbon,所以它的负载均衡配置基于Ribbon配置即可,这里使用yml简单配置负载均衡策略如下:

user-server:
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机算法

2、Feign的超时配置

如果在服务调用时出现了 “feign.RetryableException : Read timed out…”错误日志,说明Ribbon处理超时 ,我们可以配置Ribbon的超时时间:

ribbon:
ConnectTimeout: 3000 #链接超时
ReadTimeout: 6000 #读取超时

如果服务调用出现“com.netflix.hystrix.exception.HystrixRuntimeException:… timed - out and no fallback available” 错误日志,是因为Hystrix超时,默认Feign集成了Hystrix,但是高版本是关闭了Hystrix,我们可以配置Hystrix超时时间:

feign:
  hystrix:
      enabled: true #开启熔断支持
hystrix:
command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000   #hystrix超时时间

1.7、Feign开启日志调试

1、配置Feign日志打印内容

有的时候我们需要看到Feign的调用过程中的参数及相应,我们可以对Feign的日志进行配置,Feign支持如下几种日志模式来决定日志记录内容多少:

  • NONE,不记录(DEFAULT)

  • BASIC,仅记录请求方法和URL以及响应状态代码和执行时间

  • HEADERS,记录基本信息以及请求和响应标头

  • FULL,记录请求和响应的标题,正文和元数据

创建Feign配置类

@Configuration
public class FeignConfiguration {
   @Bean
   Logger.Level feignLoggerLevel() {
       return Logger.Level.FULL; //打印Feign的所有日志
  }
}

2、配置日志打印级别

配置UserFeignClient的日志打印级别,上面的配置是打印Feign的哪些内容,下面这个是配置日志框架打印日志的级别,不修改可能打印不出来日志,DEBUG打印日志调试信息。

logging:
level:
  cn.itsource.feign.client.UserFeignClient: debug

OK了,启动相关服务后,再次访问支付服务后,控制台打印如下:

image-20210817170735056

详细调用日志全部打印出来了,开始阶段方便定位问题。

1.8、Feign开启GZIP

可以通过开启Feign的数据压缩传输来节省网络开销,但是压缩数据会增加CPU的开销,所以太小的数据没必要压缩,可以通过压缩大小阈值来控制,配置如下:

feign:
compression:
  request:
    enabled: true
    min-request-size: 1024 #最小阈值,小于这个不压缩
    mime-types: text/xml,application/xml,application/json #压缩哪些类型的数据
  response:
    enabled: true


文章不错,扫码支持一下吧~
上一篇 下一篇
评论
来首音乐
光阴似箭
今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月