SpringCloud中OpenFeign远程调用

发布于:2025-02-13 ⋅ 阅读:(161) ⋅ 点赞:(0)

一,声明式实现客户端

   OpenFeign 是一种声明式的 HTTP 客户端,用于简化服务间的 HTTP 调用。使用 OpenFeign 时,只需要通过接口声明和注解,就能轻松实现远程服务的调用,避免了手动编写 HTTP 请求和响应处理的代码。

@FeignClient(value = "service-product") // feign客户端
public interface ProductFeignClient {
    // mvc注解的两种使用逻辑
    // 1. 标注在Controller上,是接受这样的请求
    // 2. 标注在FeignClient上,是发送这样的请求
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}
  • @FeignClient(value = "service-product"):标明该接口是一个 Feign 客户端,调用名为 service-product 的服务。
  • @GetMapping("/product/{id}"):定义了一个 GET 请求,路径中包含了 {id} 变量,该路径对应的就是服务端的某个接口。
  • @PathVariable("id") Long id:从路径中提取 id 参数,并传递给方法 getProductById

二,使用远程调用接口

        要使用这个接口,需要在 Spring Boot 服务中注入 ProductFeignClient 并调用其方法。示例如下:
@Autowired
private ProductFeignClient productFeignClient;

public Product getProduct(Long id) {
    return productFeignClient.getProductById(id);
}
        当调用 getProductById(id) 方法时,OpenFeign 会自动发送 HTTP 请求到 service-product 服务,并返回 Product 对象。

三,入口配置 Feign

        为了确保 Feign 能正常工作,你需要在 Spring Boot 应用中启用 Feign 客户端支持,通常在主类中添加 @EnableFeignClients 注解:
@SpringBootApplication
@EnableFeignClients
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

四,日志添加Feign Logger

        在微服务的配置文件下自定义 Feign 的日志记录器
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {

    @Bean
    public Logger.Level feignLoggerLevel() {
        // 设置日志级别
        return Logger.Level.FULL;
    }
}
     在 @FeignClient 注解中引用该配置类:
@FeignClient(value = "service-product", configuration = FeignConfig.class)
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}
        为特定 Feign 客户端配置日志:
feign:
  client:
    config:
      service-product:  # service-product 是 Feign 客户端的名称
        loggerLevel: full  # 设置日志级别为 FULL

五.超时配置

        超时配置是为了防止 Feign 客户端在调用远程服务时长时间阻塞。我们可以配置连接超时和读取超时,以确保服务调用不会无限期地等待。
application.yml 中,我们可以使用以下配置来设置 Feign 的超时时间:
feign:
  client:
    config:
      default:
        connectTimeout: 5000  # 连接超时,单位毫秒
        readTimeout: 5000     # 读取超时,单位毫秒
  • connectTimeout:设置与服务建立连接的超时时间。
  • readTimeout:设置读取服务响应的超时时间。
        如果连接超时或读取超时,会抛出 FeignException,这时可以结合重试机制或 Fallback 机制来处理错误。

六.重试机制

        Feign 默认启用了重试机制,但是我们可以根据需要自定义重试策略。重试机制会在请求失败时自动重试一定次数,通常用于处理短期网络波动或服务暂时不可用的情况。
6.1启用和配置重试机制
application.yml 中配置 Feign 的重试机制:
feign:
  client:
    config:
      default:
        retryer:
          # 最大重试次数
          maxAttempts: 3
          # 重试间隔
          period: 1000  # 单位毫秒
          # 重试间隔的扩展倍数
          maxPeriod: 5000  # 单位毫秒
6.2自定义重试器
我们希望自定义重试的逻辑,可以创建一个自定义的 Retryer 类,并将其注入到 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(1000, 5000, 3);  // 1s, 5s, max 3 attempts
    }

    @Bean
    public Logger.Level feignLoggerLevel() {
        // 设置日志级别
        return Logger.Level.FULL;
    }
}
@FeignClient 中引用这个配置:
@FeignClient(value = "service-product", configuration = FeignConfig.class)
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}

七.Feign 拦截器(Interceptor)

Feign 拦截器可以让在发送请求之前或响应之后执行自定义操作。拦截器常用于以下场景:
  • 添加请求头(如认证 Token)
  • 记录请求和响应日志
  • 修改请求参数
  • 实现请求签名
Feign 提供 RequestInterceptor 接口,允许我们自定义拦截逻辑,并在所有 Feign 请求中生效。案例添加请求头进行认证:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import java.util.UUID;

@Component
public class XTokenRequestInterceptor implements RequestInterceptor {

    /**
     * 请求拦截器
     * @param template 请求模板
     */
    @Override
    public void apply(RequestTemplate template) {
        System.out.println("XTokenRequestInterceptor .......");
        template.header("X-Token", UUID.randomUUID().toString());
    }
}
1. @Component
  • 该类被 @Component 注解,Spring Boot 会自动扫描并将其注册为 Bean,不需要手动在 FeignConfig 配置中声明。
2. implements RequestInterceptor
  • 实现 RequestInterceptor 接口,意味着 apply(RequestTemplate template) 方法会在每次 Feign 请求发送前执行。
3. apply(RequestTemplate template)
  • template.header("X-Token", UUID.randomUUID().toString());
    • 这里的 template.header 方法会为每个 Feign 请求添加 X-Token 头,并赋予一个随机生成的 UUID 作为 Token 值。
    • 这在一些应用场景下很有用,例如:
      • 需要唯一请求标识(traceId)。
      • 需要向后端传递 Token 进行认证。
        如下为前面定义好的Feign客户端,由于 上述拦截器XTokenRequestInterceptor 已经使用 @Component 注册,它会自动生效,不需要额外的 configuration 绑定。当 getProductById() 被调用时,Feign 将会在 HTTP 请求头中添加 X-Token: [UUID]
@FeignClient(value = "service-product")
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}

八,Fallback 机制

Fallback 机制是在远程调用失败时执行备选方案,通常用于当远程服务不可用时返回默认数据或做错误处理。需要定义一个类来实现 Feign 客户端接口,重写客户端中的调用方法,接口里边之前定义了一个getproductbyid,相当于按照商品的id去查商品的方法,而我们实现的这个方法其实就是兜底回调,它不一定会被调用,只有说远程调用失败以后才会走在该类中提供默认实现:
import org.springframework.stereotype.Component;

@Component
public class ProductFeignFallback implements ProductFeignClient {

    @Override
    public Product getProductById(Long id) {
        // 返回默认值或做错误处理
        return new Product(id, "Fallback Product", 0.0);
    }
}
启用 Fallback在 Feign 客户端接口中使用 fallback 属性指定 Fallback 类:
@FeignClient(value = "service-product", fallback = ProductFeignFallback.class)
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}
当远程服务调用失败时,Feign 会自动调用 ProductFeignFallback 类中的 getProductById 方法,提供备用响应,返回保底的数据,避免异常。
Fallback 的作用
  • 服务降级:当远程服务不可用时,可以提供一个默认值或错误响应,避免系统崩溃。
  • 错误处理:通过 Fallback 可以集中处理服务调用失败的逻辑,比如记录日志、发送告警等。

网站公告

今日签到

点亮在社区的每一天
去签到