Feign 远程调用服务降级

在 Spring Cloud 中,Feign 服务降级(Fallback)是指当 Feign 远程调用失败时,自动执行备用逻辑,以提高系统的稳定性和容错能力。常见的失败情况包括:

  • 目标服务宕机或不可用

  • 网络异常

  • 调用超时

如何实现 Feign 服务降级?

Spring Cloud Feign 提供 两种方式 来实现服务降级:

  1. 使用 fallback(推荐,基于类实现)

  2. 使用 fallbackFactory(可以获取异常信息)


1. 方式一:使用 fallback(简单方式)

适用于简单的降级逻辑,如返回默认数据。

2. 方式二:使用 fallbackFactory(可获取异常信息)

适用于需要日志或异常信息的情况。

① 定义 Feign 客户端

@FeignClient(name = "user-service", path = "/users", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
    @GetMapping("/{id}")
    User getUserById(@PathVariable("id") Long id);
}

② 创建 FallbackFactory

@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable cause) {
        return new UserClient() {
            @Override
            public User getUserById(Long id) {
                System.out.println("服务降级,异常原因:" + cause.getMessage());
                return new User(id, "降级用户", 0);
            }
        };
    }
}

3. 配置 Feign 超时

可以在 application.yml 中配置 Feign 超时,避免长时间等待:

feign:
  client:
    config:
      default:
        connectTimeout: 5000  # 连接超时 5s
        readTimeout: 5000     # 读取超时 5s

5. 总结

方法

适用场景

优点

fallback

逻辑简单,直接返回默认值

实现简单

fallbackFactory

需要获取异常信息

可获取 Throwable

推荐:

  • 业务简单 → fallback

  • 需要日志、异常信息 → fallbackFactory

为什么 Hystrix 被淘汰?

Hystrix 已不再维护(Netflix 停止支持),所以 Spring Cloud 2020+ 版本 改用 Resilience4j 作为熔断降级方案。

Spring Cloud 2020+ 替代方案

新版本建议用 Resilience4j,它更加轻量、灵活,并且支持:

  • 限流

  • 熔断

  • 重试

  • 降级

如果你用的是 Spring Cloud 2020+,建议使用 Resilience4j + Feign,而不是 Hystrix。


3. Resilience4j 替代 Hystrix

(1)引入依赖

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot2</artifactId>
    <version>2.0.2</version>
</dependency>

(2)配置熔断策略

resilience4j:
  circuitbreaker:
    instances:
      userService:
        failureRateThreshold: 50  # 失败率达到 50% 触发熔断
        slowCallRateThreshold: 50
        slowCallDurationThreshold: 2000ms
        minimumNumberOfCalls: 5
        slidingWindowSize: 10
        waitDurationInOpenState: 10s

(3)Feign 客户端使用 @CircuitBreaker

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/{id}")
    @CircuitBreaker(name = "userService", fallbackMethod = "fallbackUser")
    User getUserById(@PathVariable("id") Long id);

    default User fallbackUser(Long id, Throwable e) {
        System.out.println("Resilience4j 熔断触发:" + e.getMessage());
        return new User(id, "降级用户", 0);
    }
}