OpenFeign:
OpenFeign 是 SpringCloud 生态中的声明式 REST 客户端,用于简化微服务间的 HTTP 调用,让远程服务调用像调用本地方法一样直观
声明式和编程式:
对比 RestTemplate(编程式):需要手动拼接 URL、参数、处理响应,代码冗余
OpenFeign:只需要定义接口 + 注解,框架自动生成实现类完成 HTTP 请求,无需编写请求发送逻辑
注解驱动:
@FeignClient:指定要调用的远程服务名称 / 地址,绑定服务
@GetMapping/@PostMapping/@DeleteMapping:声明 HTTP 请求方式
@RequestHeader/@RequestParam/@RequestBody:声明请求携带的参数、头信息或请求体
直接定义返回的响应模型(POJO),框架自动完成 JSON/XML 到对象的序列化 / 反序列化
集成 SpringCloud 生态:
天然支持服务发现(Eureka/Nacos):可直接通过服务名调用,无需硬编码 IP 端口
集成负载均衡(Ribbon/Spring Cloud LoadBalancer):自动实现请求分发
支持熔断/降级(Sentinel/Hystrix):提升服务容错能力
声明式实现:

引入依赖:
XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

启动类开启 Feign 功能:

编写远程调用客户端:

注入并调用:

运行测试:

第三方 API:
根据接口文档确定如何发请求:



**面试题:**客户端负载均衡与服务端负载均衡区别

客户端负载均衡是把负载均衡逻辑放在调用方,客户端先从注册中心获取服务实例列表,再通过算法选择目标实例直接调用,比如 OpenFeign + LoadBalancer;
服务端负载均衡是把逻辑放在服务端或中间件,客户端只请求统一入口,由网关 / 反向代理分发请求,比如 Nginx、云负载均衡
调用日志:

配置文件:
XML
logging:
level:
org.example.order.feign: DEBUG

添加组件:

超时控制:
超时控制是保护调用方不被慢服务 / 故障服务拖垮的核心机制,通过限制建立连接和读取响应的最大等待时间,避免请求无限阻塞


connectTimeout(连接超时):
场景:商品服务宕机、网络不通时,超过 connectTimeout 就直接中断,避免长时间等待连接
readTimeout(读取超时):
场景:商品服务 API 执行慢、数据库卡顿,超过 readTimeout 就中断,避免调用方线程被占满

订单的 Feign 客户端对于商品的远程调用默认设置连接超时 10 秒,读取超时 60 秒:

配置时间:


重试机制:
远程调用超时失败后,还可以进行多次尝试,如果多次依然失败则结束调用,返回错误

当开启重试时,为了避免频繁请求压垮服务,采用指数退避算法:
初始等待时间 (period):100 ms(示例配置)
倍增规则:每次等待时间乘以 1.5,直到达到最大周期
最大等待时间 (maxPeriod):限制最长等多久(比如 1 秒),防止等待过久


拦截器:



运行测试:

Fallback:

Fallback 是服务熔断 / 降级时的兜底方案,当远程调用(如商品服务 API)超时、报错或不可用时,OpenFeign 会触发预设的兜底回调,返回预设数据而非直接抛出异常,保障订单服务的可用性和用户体验


关闭重试:

引入依赖和配置:


Sentinel:
随着微服务流行,服务间稳定性至关重要;Spring Cloud Alibaba Sentinel 以流量为切入点,从多维度保障服务稳定性:流量控制、流量路由;熔断降级;系统自适应过载保护;热点流量防护

架构原理:

流程:Ops 在 Dashboard 定义规则,Dashboard 将规则存储到配置中心,并向所有应用的 Sentinel Client 推送规则,客户端接收规则,对资源进行流量控制与保护
定义资源:
自动适配:主流框架自动适配,所有 Web 接口默认成为资源
编程式:使用 SphU API 手动定义资源
声明式:使用 @SentinelResource 注解标记资源
定义规则:
流量控制规则(FlowRule):限制请求速率、并发数
熔断降级规则(DegradeRule):对慢调用、异常比例高的资源进行降级
系统保护规则(SystemRule):根据负载、CPU 等自适应保护系统
来源访问控制规则(AuthorityRule):限制请求来源
热点参数规则(ParamFlowRule):针对热点参数进行限流
工作原理:

用户请求访问资源,Sentinel 对请求进行规则检查:若未违反规则:直接放行,结束流程;若违反规则:抛出异常,检查是否配置兜底处理(fallback),无:返回默认错误信息;有:执行 fallback 逻辑,返回降级结果,流程结束
基础场景:
整合使用:

下载地址:https://github.com/alibaba/Sentinel/releases
启动控制台:
bash
java -jar sentinel-dashboard-1.8.8.jar



引入依赖:
XML
<!-- sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置连接:


运行微服务:

添加注解定义资源:



设置流控规则每秒只能通过一个请求:


刷新频率过高报错:

异常报错:

Web 接口:
创建自定义错误返回对象:

java
@Data
public class R {//返回给前端的json数据
private Integer code;
private String msg;
private Object data;
public static R ok(){
R r = new R();
r.setCode(200);
return r;
}
public static R ok(String msg,Object data){
R r = new R();
r.setCode(200);
r.setMsg(msg);
r.setData(data);
return r;
}
public static R error(){
R r = new R();
r.setCode(500);
return r;
}
public static R error(Integer code,String msg){
R r = new R();
r.setCode(code);
r.setMsg(msg);
return r;
}
}
自定义处理异常:

java
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
//JSON序列化工具
private ObjectMapper objectMapper = new ObjectMapper();
/**
* 处理Sentinel拦截的阻塞异常,返回自定义JSON结果
* @param httpServletRequest 请求对象
* @param httpServletResponse 响应对象
* @param s 触发限流的资源名
* @param e Sentinel阻塞异常
*/
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
String s, BlockException e) throws Exception {
//设置响应格式:JSON+UTF-8
httpServletResponse.setContentType("application/json;charset=utf-8");
//获取响应输出流,用于写入JSON结果
PrintWriter writer = httpServletResponse.getWriter();
//构建自定义错误返回对象
R error = R.error(500,s + "被Sentinel限制了,原因:" + e.getClass());
//序列化并写入响应
String json = objectMapper.writeValueAsString(error);
//将JSON字符串写入响应体,返回给前端
writer.write(json);
writer.flush();
writer.close();
}
}
项目重新启动后需重新添加流控:


@SentinelResource:

由于没有指定任何一个异常处理机制,所以是默认异常处理:

用 blockHandler 指定降级兜底方法,保证触发限流 / 熔断时接口不直接报错,返回友好结果:


java
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
ProductFeignClient productFeignClient;
@SentinelResource(value = "createOrder",blockHandler = "createOrderFallback")//定义资源
@Override
public Order createOrder(Long productId, Long userId) {
//直接调用,底层自动发起 HTTP 请求
Product product = productFeignClient.getProductById(productId);
Order order = new Order();
order.setId(1L);
//总金额
order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
order.setUserId(userId);
order.setNickName("zhu");
order.setAddress("木朱");
//远程查询商品列表
order.setProductList(Arrays.asList(product));
return order;
}
//兜底回调
public Order createOrderFallback(Long productId, Long userId, BlockException e) {
Order order = new Order();
order.setId(0L);
order.setTotalAmount(new BigDecimal("0"));
order.setUserId(userId);
order.setNickName("未知用户");
order.setAddress("异常信息:" + e.getClass());
return order;
}
}

OpenFeign 调用:

由于之前指定了远程调用的兜底回调,所以被执行

SphU 硬编码:
抛出异常的方式定义资源:SphU 包含了 try-catch 风格的 API,用这种方式,当资源发生了限流之后会抛出 BlockException,这个时候可以捕捉异常,进行限流之后的逻辑处理
java
try (Entry entry = SphU.entry("resourceName") {
// 被保护的业务逻辑
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 在此处进行相应的处理操作
}
流控规则:

客户端突发大量请求时,Sentinel 拦截超额请求,仅放行合规请求,其余被丢弃,从而保护系统资源不被耗尽,避免服务雪崩

资源名:要限流的接口 / 资源标识(如 /create)
针对来源:限制调用来源,default 代表不区分来源
阈值类型:
QPS:按每秒请求数限流
并发线程数:按同时处理的线程数限流
单机阈值:单台机器允许的最大阈值(如 QPS=10 表示每秒最多 10 个请求)
是否集群:是否对集群内所有机器统一限流(默认不勾选,单机限流)

是否集群:勾选后开启集群限流,由 Token Server 统一分配流量配额,而非单机各自限流
集群阈值模式:
单机均摊:将总阈值平均分配给集群中每台机器(如总阈值 100、5 台机器,则每台单机阈值为 20)
总体阈值:整个集群共享一个总阈值,所有机器的请求总和不超过该值(如总阈值 100,无论多少机器,集群每秒最多 100 个请求)
失败退化:勾选后,若 Token Server(集群限流的中心节点)不可用,系统会自动退化到单机限流模式,避免因集群组件故障导致服务不可用,保证系统稳定性

流控模式:

直接:对当前资源直接执行限流规则,请求超过阈值时直接拦截,是最基础的限流模式
**链路:**只对指定调用链路入口的请求进行限流,精准控制某条调用链的流量(比如资源 B(createOrder)被资源 A(/create)和资源 C(/seckill)调用,只限制从资源 C(/seckill)进入的流量,不限制从资源 A(/create)进入的流量)
测试:




仅对秒杀创建订单有效:

**关联:**当关联资源达到阈值时,对当前资源进行限流(比如读资源压力大时,限制写资源的流量,保障读服务稳定)



流控效果:

**快速失败:**请求超过阈值时立即拒绝,直接抛出(Blockexception)异常,响应最快,适合对延迟敏感的场景







**Warm Up(预热):**阈值从一个较小值缓慢提升到设定值,避免冷启动时流量突增压垮系统,适合服务刚启动的场景



逐步增加:

**排队等待:**让请求以固定速度通过,超过的请求排队等待,超时未处理则拒绝,适合脉冲流量场景(如秒杀)





熔断规则:

切断不稳定调用:当依赖服务(如 Service D)故障时,快速拒绝调用,避免请求堆积
快速返回不积压:直接返回降级结果,不占用调用方线程资源
避免雪崩效应:防止单个服务故障扩散到整个调用链路,保障系统整体可用
断路器工作原理:

Closed(关闭):正常状态,允许请求通过;在统计时长内,若慢调用 / 异常比例 / 异常数超过阈值,切换为 Open
Open(打开):熔断生效,直接拒绝所有请求;等待熔断时长后,自动进入 Half-Open 状态
Half-Open(半开):放行少量探测请求,若探测成功则恢复为 Closed,若失败则回到 Open


资源名:要熔断保护的目标资源
熔断策略:
**慢调用比例:**按慢调用(响应超过最大 RT)的占比触发熔断
最大 RT:慢调用判定阈值(单位 ms,如是 1000ms,即响应 > 1s 算慢调用)
比例阈值:触发熔断的占比阈值(如 0.8,即慢调用 / 异常占比 ≥ 80% 时熔断)
熔断时长:熔断打开后持续拒绝请求的时间(如 30s 之后进入半开探测)
最小请求数:统计窗口内至少达到该请求数才会判断熔断(如 5,避免少量请求误判)
统计时长:统计慢调用 / 异常的时间窗口(如 1000ms,即 1 秒内统计)


**异常比例:**按请求中异常的占比触发熔断




熔断后:


**异常数:**按统计窗口内的异常总数触发熔断


热点规则:
热点规则是针对请求参数的精细化限流,只对包含特定参数的请求做限流,适合限制高频访问的热点参数(比如热门商品 ID、用户 ID)



需求一:


不携带此参数:


需求二:


需求三:



改为处理所有的异常:
java
public Order seckillFallback(Long userId, Long productId, Throwable exception){
System.out.println("seckillFallback...");
Order order = new Order();
order.setId(productId);
order.setUserId(userId);
order.setAddress("异常信息:" + exception.getClass());
return order;
}
重新测试:

兜底回调:
