服务调用

返回 Spring Cloud

Spring Cloud 服务间调用的主流方案是 OpenFeign(声明式 HTTP 客户端),底层集成了 Spring Cloud LoadBalancer 实现客户端负载均衡,并支持 Resilience4j 熔断。

OpenFeign

依赖

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

启用

@SpringBootApplication
@EnableFeignClients
public class ConsumerApp { ... }

定义 Feign 客户端

@FeignClient(
    name = "order-service",
    path = "/orders",
    fallback = OrderClientFallback.class
)
public interface OrderClient {
 
    @GetMapping("/{id}")
    Order getOrder(@PathVariable("id") Long id);
 
    @PostMapping
    Order createOrder(@RequestBody CreateOrderRequest req);
 
    @GetMapping
    Page<Order> listOrders(@RequestParam("page") int page,
                           @RequestParam("size") int size);
}

降级实现(fallback)

@Component
public class OrderClientFallback implements OrderClient {
 
    @Override
    public Order getOrder(Long id) {
        return Order.defaultOrder();
    }
 
    @Override
    public Order createOrder(CreateOrderRequest req) {
        throw new ServiceUnavailableException("订单服务暂不可用");
    }
 
    @Override
    public Page<Order> listOrders(int page, int size) {
        return Page.empty();
    }
}

降级工厂(可获取异常信息)

@Component
public class OrderClientFallbackFactory
    implements FallbackFactory<OrderClient> {
 
    @Override
    public OrderClient create(Throwable cause) {
        return new OrderClient() {
            @Override
            public Order getOrder(Long id) {
                log.error("调用 order-service 失败, id={}", id, cause);
                return Order.defaultOrder();
            }
            // ...
        };
    }
}

超时配置

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            connect-timeout: 2000
            read-timeout: 5000
          order-service:
            connect-timeout: 1000
            read-timeout: 3000
          logger-level: FULL   # NONE / BASIC / HEADERS / FULL

重试配置

@Bean
public Retryer feignRetryer() {
    // 初始间隔 100ms,最大间隔 1s,最多重试 3 次
    return new Retryer.Default(100, 1000, 3);
}

请求拦截器(统一传 Token)

@Component
public class FeignAuthInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        String token = TokenHolder.get();
        if (token != null) {
            template.header("Authorization", "Bearer " + token);
        }
    }
}

文件上传

@FeignClient(name = "file-service")
public interface FileClient {
    @PostMapping(value = "/upload",
                 consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    String upload(@RequestPart("file") MultipartFile file);
}

集成 Resilience4j 熔断

spring:
  cloud:
    openfeign:
      circuitbreaker:
        enabled: true

与 RestTemplate / WebClient 对比

特性OpenFeignRestTemplateWebClient
编程模型声明式接口命令式响应式
负载均衡自动集成@LoadBalanced@LoadBalanced
熔断集成原生支持需手动需手动
流式响应不支持不支持支持
推荐场景同步 RPC遗留代码响应式

相关链接

Spring Cloud

架构

数据库 / 分布式