SpringCloud

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

访问 http://localhost:8080

引入依赖:

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;
}

重新测试:

兜底回调:

相关推荐
wellc2 小时前
Spring Boot 热部署
java·spring boot·后端
金銀銅鐵2 小时前
[Java] 从 class 文件看动态代理
java·后端
多租户观察室3 小时前
工作流新生态:2026年工作流与Coding的重新分工
前端·人工智能·后端·低代码
Carsene3 小时前
开源项目文档架构设计:Git Submodule 实现文档与代码的优雅分离
前端·后端
用户8356290780513 小时前
Python 实现 Word 文档图片插入与排版技巧
后端·python
AI茶水间管理员3 小时前
部署70B大模型到底要多大显存?一文算清所有账
人工智能·后端
树獭叔叔3 小时前
向量数据库的双索引架构:HNSW与Payload的协同机制
后端·aigc·openai
yuweiade3 小时前
Spring Boot 集成 Kettle
java·spring boot·后端
武超杰4 小时前
Spring MVC进阶与SSM整合实战
java·spring·mvc