springcloud-fegin 组件调用

一、Feign 概述

Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。

在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。

Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。

1.1 Fegin 常用注解

OpenFeign 常用注解OpenFeign 声明式服务调用和负载均衡组件,因此它的核心是使用注解 + 接口的方式实现服务调用,所以了解 OpenFeign 的注解就至关重要了。 对于 Feign 框架来说,它只支持 Feign 注解和 JAX-RS 注解,但 OpenFeign 在 Feign 的基础上还增加了对 Spring MVC 注解的支持,例如 @RequestMapping、@GetMapping 和 @PostMapping 等注解。 OpenFeign 常用注解有以下几个:

  • @EnableFeignClients:该注解用于开启 OpenFeign 功能,当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。
  • @FeignClient:该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。
  • @RequestMapping:向服务提供者发起 Request 请求(默认为 GET 方式请求),这里需要注意@RequestMapping/@GetMapping/@PostMapping 和 Spring MVC 中的同名注解的含义是完全不同的。
  • @GetMapping:向服务提供者发起 GET 请求。
  • @PostMapping:向服务提供者发起 POST 请求。

1.2 Feign调用过程

OpenFeign 是用在服务消费端的,有消费端就得有服务提供端,它们的关系如下图所示:
在这里插入图片描述
所以我们先要创建一个服务提供者 Provider;提供者fegin在调用时没有什么特别注意的,提供者没有什么需要注意的,只需要把提供者注入到注册中心,消费者就会从注册中心获取提供者。消费搭建搭建如下

二、组件引入搭建

1.在服务消费者端引入fegin 依赖包

在服务消费者端引入jar包

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

如果配合注册中心使用的话还需要引入注册中心的客户端包

      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2. 在启动类中启动fegin 功能

在启动类上加 @EnableFeignClients 注解,如果你的 Feign 接口定义跟你的启动类不在同一个包名下,还需要制定扫描的包名 @EnableFeignClients(basePackages=“com.fangjia.api.client”)


@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"api.config.env.client"})
public class AmasterWorkServerApplication {

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

}

说明 :
@EnableFeignClients 需要指定 fegin的 接口feginClient 所在的接口位置 ,@EnableFeignClients(basePackages ={XXX } 属性,否在 在spring 启动的时候注入 feginClient 所在的接口注入不到spring中,启动会报注入失败异常!

3. 声明FeignClient接口

3.1 @FeignClient 注解属性说明

@FeignClient 注解:这个注解标识当前是一个 Feign 的客户端,value 属性是对应的服务名称

  • path: 服务调用的统一前缀
  • name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
  • url: url一般用于调试,可以手动指定@FeignClient调用的地址
  • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
  • configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
  • allback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@FeignClient(name = "amaster-config-env"/*, url = "远程服务URL"*/,path = "amaster-config-env")
public interface ConfigEnvServiceClient {

    @RequestMapping(value="/env/get/env/all/v1",method = RequestMethod.GET)
    public List<String> getEnvConfig();
}

在这里插入图片描述
在FeignClient 接口中需要用@FeignClient 注解标注为Feign 客户端,还需要指定 消费这服务名,服务的容器path 路径。如果不指定 path 话,在接口调用的时候会报找不到feign报UnknownHostException:服务名解决方案 ,或者报404 找不到消费者的接口路径。再指定url属性的时候,feginClient 客户端优先使用url进行调用。

如果FeignClient接口参数少了@RequestBody或@RequestParam注解会造成调用服务提供者时出现参数为空现象。(当然无论是服务提供者还是调用者都要加上注解)

4.测试

调用消费者
GET http://localhost:9005/amaster-work-server/env/get/config/env/all/v1
会把提供者接口的结果返回

[“amaster-report-server prod hello world123”]

如果走网关调用也会输出
http://localhost:8070/amaster-work-server/env/get/config/env/all/v1

[“amaster-report-server prod hello world123”]

三. fegin的请求拦截处理

对于Fegin 调用前的拦截调用统一处理可以使用, feign的RequestInterceptor,拦截器进行拦截处理,比如在调用前可以统一给调用的header添加token等处理

class FeignRequestHeaderInterceptor implements RequestInterceptor {

	@Override
	public void apply(RequestTemplate requestTemplate) {
		MethodMetadata methodMetadata = requestTemplate.methodMetadata();
		// 这个就是当前被@FeignClient注解的feign接口类型
		Class<?> classDecorateByFeignClientAnnotation = methodMetadata.method().getDeclaringClass();
		
		// 获取到path之后, 向rquest header塞入一个约定的键值对, 或者基于ThreadLocal, 向下传递给我们的`LoadBalancerFeignClientEx`
		......
	}
}


feign技巧 - 同时支持基于url和服务名的调度:https://blog.csdn.net/lqzkcx3/article/details/130269543

四、Feign 的 Fallback和FallbackFactory

@FeginClient 属性中的Fallback和 FallbackFactory可以帮助我们在使用Feign去调用另一个服务时,如果出现了问题,走服务降级,返回一个错误的数据,避免功能因为一个服务出现问题,全部失效。

4.1 fallBack 方式

4.1.1 定义fallBack类

ConfigEnvServiceClientFallBack 回调实现,由spring创建使用@Component(其他的注册也可以)注解


@Component
public class ConfigEnvServiceClientFallBack implements ConfigEnvServiceClient {
    @Override
    public List<String> getEnvConfig() {
        return Arrays.asList("Fallback response");
    }
}

在这里插入图片描述
fallBack 类要实现feginCleint 的接口,并且需要声明为一个bean组件,这样当熔断发生的时候 hystris 就会从spring容器中拿到这个接口的兜底fallVBack方法;
注意fallBack 类的实现类也需要被ComponentScan 也要扫描到你的fallback及包 扫描到

HystrixTargeter.targetWithFallback方法实现了@FeignClient.fallback处理逻辑,通过源码可以知道UserFeignFallback回调类是从Spring容器中获取的,所以ConfigEnvServiceClientFallBack 由spring创建。

4.1.2 在FeignClient 的快速失败策略(fallback 、fallBackFactory)上定义快速失败的实现类

@FeignClient(name = "amaster-config-env"
/*, url = "远程服务URL"*/,
        path = "amaster-config-env",
        fallback = ConfigEnvServiceClientFallBack.class
       /*fallbackFactory = ""*/)
public interface ConfigEnvServiceClient {

    @RequestMapping(value="/env/get/env/all/v1",method = RequestMethod.GET)
    public List<String> getEnvConfig();
}

在这里插入图片描述

4.1.3 测试

当服务提供者接口500或者异常时候则,消费者的口的fallBack就会执行快速失败策略
当服务调用成功的时候输出

["amaster-report-server prod hello world123"]

当消费服务异常或者接口异常的时候返回

["Fallback response"]

4.2FallbackFactory工厂方式

fallBack上面的实现方式简单,但是获取不到HTTP请求错误状态码和信息 ,这时就可以使用工厂模式来实现Fallback

同样工厂实现类也要交由spring管理,同时结合ConfigEnvServiceClientFallBack使用,这里需要注意的create方法返回值类型一定要实现Feign接口

4.2.1 定义FallBackFactory 实现类

package com.zhang.buiness.amaster.workserver.client.fallback;

import com.zhang.buiness.amaster.workserver.client.fegin.ConfigEnvServiceClient;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 *
 * 相比于fallBack,可以打印出 fallBack的异常信息
 */
@Component
@Slf4j
public class ConfigEnvServiceClientFallBackFactory implements FallbackFactory<ConfigEnvServiceClient> {

    private final ConfigEnvServiceClientFallBack configEnvServiceClientFallBack;

    public ConfigEnvServiceClientFallBackFactory(ConfigEnvServiceClientFallBack configEnvServiceClientFallBack) {
        this.configEnvServiceClientFallBack = configEnvServiceClientFallBack;
    }


    @Override
    public ConfigEnvServiceClient create(Throwable throwable) {
        log.error("ConfigEnvServiceClient fall Back {}",throwable.getMessage(),throwable);
        return configEnvServiceClientFallBack;
    }
}

4.2.1 在@FeginClient中使用FallBackFactory

@FeignClient(name = "amaster-config-env"
       /*, url = "远程服务URL"*/,
        path = "amaster-config-env",
        /*fallback = ConfigEnvServiceClientFallBack.class*/
       ,fallbackFactory = ConfigEnvServiceClientFallBackFactory.class)
public interface ConfigEnvServiceClient {

    @RequestMapping(value="/env/get/env/all/v1",method = RequestMethod.GET)
    public List<String> getEnvConfig();
}

在这里插入图片描述

4.2.2 测试

提供者接口正常

["amaster-report-server prod hello world123"]

提供者异常

["Fallback response"]

控制台打印日志
在这里插入图片描述

4.3 fallBack 执行调用不成的排查点

以下是feign调用出现的问题检查点
1、激活
2、注解
3、fallback
4、fallback + @Component
5、激活Feign中要扫描到你的feign及包
6、ComponentScan 也要扫描到你的fallback及包
7、配置的拦截器
8、配置的拦截器中,一定一定一定要加log打印,(重中之重,有助于你排查问题,不会焦头烂额)
9、如果配置熔断优化策略,配置好超时时间(从一个请求的开始到rpc调用且包含rpc中的执行时间)
10、**检查返回类型是否序列化,即非interface

五 自定义fegin 请求 ErrorDecoder

https://blog.csdn.net/sun_shaoping/article/details/82079287

六、fegin传递参数与spring MVC 传参的不同 (待定)

Feign默认使用@RequestBody,这就是上面name参数为null的原因,@RequestBody(只能有一个)一般用于传递对象,如果参数中出现多个对象可以使用Map来传递对象

如果你传递的参数,比较复杂时,默认会采用 POST 的请求方式。
传递单个参数时,推荐使用 @PathVariable (Restful 风格),如果传递的单个参数比较多,这里也可以采用 @RequestParam ,不要省略 value 属性。
传递对象信息时,统一采用 json 的方式,添加 @RequestBody 。
Client接口必须采用 @RequestMapping 。

@FeignClient(name = "hello")  
public interface IHelloService {  
  @RequestMapping(value = "/hello",method = RequestMethod.GET)  
  String saveBook(@RequestBody Book book);  
}  

参考博客:
https://blog.csdn.net/justry_deng/article/details/80785973
https://blog.csdn.net/qq_34912478/article/details/81387422

七、 服务之间调用的几种方式比较待定(待定)

三种方式对比:

RestTemplate 方式:
String result = restTemplate.getForObject(url+“search”, String.class);
RestTemplate 整合 Ribbon方式:
String result = restTemplate.getForObject(“//SEARCH/search”, String.class);
Feign 方式:
String result = searchClient.search();
使用RestTemplet 进行服务调用时候的负载均衡处理

https://blog.csdn.net/baidu_39378193/article/details/125029430
https://blog.csdn.net/djrm11/article/details/114526346

八、fegin的负载均衡、超时、重试配置

fegin 请求重试配置

Feign 是一个声明式的Web服务客户端,用来简化HTTP远程调用。要配置Feign的负载均衡和重试机制,你需要在Spring Cloud项目中进行如下配置:

使用@FeignClient注解时,可以指定服务名来使用Ribbon的负载均衡。

重试机制可以通过配置类添加Retryer或Request.Options来实现。

下面是一个配置Feign重试机制的例子:

import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class FeignConfig {
 
    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(100, 0); // 示例:初始间隔100ms,最大重试0次
    }
}

然后在你的Feign客户端接口上使用这个配置:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
 
@FeignClient(name = "my-service", configuration = FeignConfig.class)
public interface MyServiceClient {
 
    @GetMapping("/api/resource")
    String getResource();
}

Feign默认集成了Ribbon,利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。如果要对fegin 进行负载均衡、重试、超时配置可以对ribbon进行配置

配置重试机制:
Feign 默认集成了Feign的重试机制,可以通过配置文件来开启和设置重试参数。Feign 默认集成了Feign的重试机制,可以通过配置文件来开启和设置重试参数。


feign:
  client:
    config:
      default:
        connectTimeout: 1000 # 连接超时时间(毫秒)
        readTimeout: 3000 # 读取超时时间(毫秒)
        loggerLevel: basic # 日志级别
        errorDecoder: com.example.CustomErrorDecoder # 错误解码器
        retryer: com.example.CustomRetryer # 重试机制

自定义重试机制,需要实现Retryer接口:

public class CustomRetryer implements Retryer {

    private final int MAX_ATTEMPTS = 5;
    private final int READ_TIMEOUT = 3000; // 重试读取超时时间

    @Override
    public void continueOrPropagate(RetryableException e) {
        if (e.getCause() instanceof FeignException) {
            FeignException cause = (FeignException) e.getCause();
            if (cause.status() >= 500 && cause.status() <= 599) {
                if (attempts++ >= MAX_ATTEMPTS) {
                    // 重试次数超过最大值,抛出异常
                    throw e;
                }
                try {
                    // 实现重试逻辑,这里是简单的等待重试
                    Thread.sleep(READ_TIMEOUT);
                } catch (InterruptedException interrupted) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    private int attempts;
}

以上代码展示了如何配置Feign的负载均衡和重试机制。通过配置文件可以设置Ribbon的策略和Feign的超时时间、日志级别以及自定义的错误解码器和重试机制。

fegin 请求超时配置

如果需要自定义Ribbon的配置,可以在application.properties或application.yml中设置:

超时配置方式一

# 指定Ribbon的配置,比如连接超时时间、读超时时间等
ribbon.ConnectTimeout=1000
ribbon.ReadTimeout=2000

超时配置方式二

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
 
@FeignClient(name = "example-service", url = "http://localhost:8080",
        configuration = FeignClientConfiguration.class)
public interface ExampleClient {
    @GetMapping("/endpoint")
    String getData();
}
 
@Configuration
class FeignClientConfiguration {
    // 使用@Bean定义Feign的配置
    @Bean
    public Request.Options feignOptions() {
        return new Request.Options(
                connectTimeoutMillis: 5000, // 连接超时时间(毫秒)
                readTimeoutMillis: 5000); // 读取超时时间(毫秒)
    }
}

在上面的代码中,FeignClientConfiguration 类中定义了一个Request.Options的Bean,这个Bean包含了连接超时和读取超时的设置。这些值会覆盖默认的配置。

确保你的项目中已经添加了Spring Cloud OpenFeign依赖,并且开启了Feign客户端的支持。

fegin 负载均衡策略配置

配置负载均衡方式一:

Feign 默认集成了Ribbon,因此可以直接通过配置Ribbon的方式来设置负载均衡策略

# 对特定服务配置负载均衡策略,如降级策略
service-id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

在上面的配置中,service-id是你要配置的服务名称,RandomRule是负载均衡策略,表示使用随机策略。你可以将RandomRule替换为RoundRobinRule(轮询策略)或BestAvailableRule(最少活跃调用数策略)来使用其他策略。

需要注意的是,Spring Cloud 2020.0版本开始已经弃用了Ribbon,并推荐使用Spring Cloud LoadBalancer作为默认的负载均衡器。因此,在新版本的Spring Cloud中,Feign将默认与Spring Cloud LoadBalancer集成。

要在Spring Cloud 2020.0及之后的版本中使用Spring Cloud LoadBalancer进行负载均衡配置,你需要确保你的项目中包含了spring-cloud-starter-loadbalancer依赖,并且没有包含spring-cloud-starter-netflix-ribbon依赖。配置方式与Ribbon类似,但具体的类名和配置选项可能会有所不同。

Feign 的负载均衡配置策略第二种方式

Feign 默认集成了Ribbon,因此可以直接通过配置Ribbon的方式来设置负载均衡策略。

@Configuration
public class FeignConfig {

    @Bean
    public IRule ribbonRule() {
        // 可以选择不同的轮询策略,例如:
        return new RandomRule(); // 随机策略
    }
}

通过配置文件可以设置Ribbon的策略和Feign的超时时间、日志级别以及自定义的错误解码器和重试机制。

负载均衡的三种常见方式

Feign 本身并不直接进行负载均衡配置,它依赖于 Ribbon 或 Spring Cloud LoadBalancer(在Spring Cloud 2020.0及之后的版本中)来实现客户端负载均衡。在 Spring Cloud 的生态系统中,Feign 与 Ribbon 或 Spring Cloud LoadBalancer 集成,以提供声明式的服务调用和负载均衡功能。

负载均衡的三种常见方式(不仅仅适用于Feign,而是适用于大多数负载均衡器和服务发现机制)包括:

  • 轮询(Round Robin):
    轮询是最简单的负载均衡策略,它按照顺序轮流将请求发送到每个服务实例。当达到列表的末尾时,它通常会重新开始。这种策略假设所有服务实例的处理能力大致相同,并且不需要额外的监控或度量来决定如何分发请求。

  • 随机(Random):
    随机策略选择服务实例时是完全随机的。这种策略对于避免某些服务实例过载很有用,因为它不依赖于任何特定的顺序或规则。

  • 最少连接数(Least Connections):
    最少连接数策略选择具有最少活动连接的服务实例。这种策略有助于将新请求分发到尚未处理过多请求的服务实例,从而实现负载的均匀分布。

九、OpenFeign 介绍

OpenFeign 介绍OpenFeign 的全称是 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用和负载均衡组件。它的出现就是为了替代已经进入停更维护状态的 Feign(Netflix Feign)的。也就是说 OpenFeign(Spring Cloud OpenFeign)是 Feign 的升级版,它们的关系如下图所示

在这里插入图片描述
因为 Feign 停更维护了,所以 Spring 官方需要推出了一个新的新的框架来对 Feign 功能进行升级和扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值