实战一:订单与库存两个服务的调用链(Feign+降级)
本章打通一条最小调用链:请求经订单服务(order-service)调用库存服务(stock-service)扣减库存,库存不可用时触发 Feign 降级返回兜底。版本锚点同第 01 章:JDK 17/21 + Spring Boot 3.5.x + Spring Cloud 2025.0.x + spring-cloud-alibaba 2025.0.0.x(Nacos 注册发现),以官方文档为准。
依赖与配置
order-service 引入 Nacos 注册发现、OpenFeign 与熔断封装(fallback 由 Resilience4j 实现):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
# order-service application.yml
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
openfeign:
circuitbreaker:
enabled: true # 开启 Feign 熔断,fallback 才生效
库存服务侧
扣减接口(controller + service,含校验与锁)由库存服务自身实现,写法与普通 Web 接口一致,从略。
订单服务:Feign 接口、降级类与调用
// 1) Feign 接口:声明远程调用;fallback 指定降级类
@FeignClient(name = "stock-service", path = "/stock", fallback = StockFeignFallback.class)
public interface StockFeignClient {
@PostMapping("/deduct")
Result<Void> deduct(DeductReqDTO req);
}
// 2) 降级类:必须由 Spring 管理,返回兜底结果
@Component
public class StockFeignFallback implements StockFeignClient {
@Override
public Result<Void> deduct(DeductReqDTO req) {
return Result.fail(503, "库存服务暂不可用,已降级");
}
}
// 3) 业务层:扣减失败时挂起订单,走异步补偿而非直接失败
@Service
@RequiredArgsConstructor
public class OrderService {
private final StockFeignClient stockFeignClient;
public Result<Void> createOrder(OrderReqDTO order) {
Result<Void> r = stockFeignClient.deduct(toDeductReq(order));
if (!r.isSuccess()) {
order.setStatus(OrderStatus.PENDING_STOCK);
return Result.fail("库存扣减暂不可用,订单已挂起");
}
order.setStatus(OrderStatus.CREATED);
return Result.ok();
}
}
超时与熔断参数
按 Feign 客户端名分组设置连接/读取超时(键名以官方文档为准);熔断参数同 Resilience4j 章节(窗口 10、失败率 50%、打开 10s)。注意熔断器名与 Feign 客户端名的对应关系随版本有差异,以官方文档为准。
运行与验证
- 启动 Nacos、stock-service、order-service。
- 正常请求扣库存:两服务日志均有调用记录。
- 停掉 stock-service 再请求:返回“库存服务暂不可用,已降级”,order-service 不报错、不堆线程。
- 重启 stock-service:实例重新注册后请求自动恢复。
常见问题
- fallback 不生效:需引入 circuitbreaker 依赖且 enabled=true,降级类被 Spring 管理。
- 契约不一致:Feign 方法签名与服务端一致,DTO 放公共契约模块。
- 参数过严:短超时 + 低熔断阈值会让偶发抖动也降级,需结合压测调优。
小结
一条 Feign 调用链 = 注册发现 + 接口契约 + 超时熔断 + 降级兜底;停掉 stock-service 再请求是最低成本的降级演练。