为了账号安全,请及时绑定邮箱和手机立即绑定

Sentinel+Feign熔断学习入门简明教程

概述

本文详细介绍了Sentinel与Feign的熔断学习入门,涵盖了Sentinel和Feign的基本概念和主要功能,并阐述了如何在Spring Boot项目中实现Sentinel与Feign的集成,包括环境搭建、熔断功能的实现以及实例项目的搭建。

Sentinel与Feign简介
Sentinel基础概念

Sentinel是阿里巴巴开源的一款轻量级、高性能的流量控制组件,能够提供流量控制、熔断降级、系统保护等功能,有效防止系统在流量高峰时出现雪崩效应。

主要功能

  1. 流量控制:根据业务规则限制进入系统的流量。
  2. 熔断降级:当系统服务出现故障时,快速返回错误信息,避免连锁故障。
  3. 系统保护:实时监控系统负载,并根据负载情况自动调整流量,保证系统的稳定运行。
  4. 热点防护:对热点数据进行流量控制,防止因热点数据访问过频繁导致系统崩溃。

核心概念

  1. 资源:Sentinel中的“资源”可以是一个接口、一个方法,或者更多的抽象定义,代表系统中可监控的单元。
  2. 规则:规则定义了对资源的保护策略,例如QPS限制、响应时间控制等。
  3. 流控:当资源的访问量达到一定阈值时,自动减少流量,避免过载。
  4. 降级:在系统故障时,自动切换到备用策略,保证系统可用性。
  5. 系统保护:监控系统自身健康状态,如CPU、负载等。
Feign基础概念

Feign是一个声明式的Web服务客户端,使得写Web服务客户端变得更加容易。Feign提供了简单的方法来定义HTTP客户端,结合了Ribbon和Eureka的负载均衡功能,以及Hystrix的熔断降级功能。

主要特性

  1. 声明式API:通过注解定义HTTP请求,简化客户端开发。
  2. 负载均衡:Feign集成了Ribbon,实现负载均衡。
  3. 熔断降级:Feign集成了Hystrix,实现服务的熔断和降级。
  4. 异步支持:支持异步调用,提高系统响应速度。

核心概念

  1. 客户端:Feign客户端是通过注解定义的接口,映射HTTP请求。
  2. HTTP请求:通过注解定义HTTP请求的方法,如GET、POST、PUT等。
  3. 负载均衡:Feign客户端自动实现负载均衡。
  4. 熔断降级:当服务不可用时,Feign客户端立即返回默认的错误信息,而不是长时间等待。
  5. 异步调用:Feign支持异步调用,提高系统响应速度。
Sentinel与Feign集成环境搭建
快速搭建Spring Boot项目

创建项目

  1. 创建一个新的Spring Boot项目,例如,使用Spring Initializr创建。
  2. 选择Spring Boot版本,选择Web和Actuator作为依赖。

项目结构

sentinel-feign-demo
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── sentinelfeign
│   │   │               ├── SentinelFeignApplication.java
│   │   │               ├── controller
│   │   │               │   └── HelloController.java
│   │   │               └── service
│   │   │                   └── HelloService.java
│   │   └── resources
│   │       ├── application.yml
│   │       └── sentinel-feign-demo.yml
└── pom.xml

Maven依赖

pom.xml中添加必要的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Spring Boot应用启动类

创建SentinelFeignApplication.java,作为Spring Boot应用的启动类:

package com.example.sentinelfeign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.alibaba.sentinel.EnableSentinelWebAutoConfiguration;

@SpringBootApplication
@EnableFeignClients
@EnableSentinelWebAutoConfiguration
public class SentinelFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelFeignApplication.class, args);
    }
}
添加Sentinel与Feign依赖

在上面的pom.xml文件中已经添加了Sentinel和Feign的依赖。

Sentinel依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

Feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Feign熔断功能实现
Feign熔断的基本原理

Feign的熔断功能通过Hystrix实现。当服务不可用时,Feign客户端会立即返回一个默认的错误信息,而不是长时间等待。

主要步骤

  1. 服务调用:Feign客户端发起服务调用。
  2. 超时检测:如果服务调用超时,进入熔断降级流程。
  3. 熔断器状态转换:Hystrix会判断当前熔断器状态(开启、半开、关闭)。如果在熔断状态,直接返回熔断逻辑的结果;如果在半开状态,则尝试调用实际服务;如果在关闭状态,则正常调用。
  4. 熔断逻辑:如果服务调用失败,Hystrix会记录错误,并触发熔断器状态转换,进入熔断状态。
  5. 熔断恢复:在熔断状态下,Hystrix会定期尝试恢复调用,如果连续成功调用,熔断器会从熔断状态转换到半开状态,然后尝试调用实际服务,如果再次失败,熔断器会回到熔断状态。
实现Feign客户端的熔断保护

服务端代码

在服务端实现一个简单的接口,提供sayHello方法:

package com.example.sentinelfeign.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String sayHello(String name) {
        if ("error".equals(name)) {
            throw new RuntimeException("Service error");
        }
        return "Hello, " + name;
    }
}

Feign客户端代码

在客户端定义一个Feign客户端,调用服务端的sayHello方法:

package com.example.sentinelfeign.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "hello-service")
public interface HelloClient {
    @GetMapping("/hello")
    String sayHello(@RequestParam("name") String name);
}

控制器代码

创建一个控制器来调用Feign客户端:

package com.example.sentinelfeign.controller;

import com.example.sentinelfeign.service.HelloClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    private final HelloClient helloClient;

    public HelloController(HelloClient helloClient) {
        this.helloClient = helloClient;
    }

    @GetMapping("/hello")
    public String sayHello(@RequestParam("name") String name) {
        return helloClient.sayHello(name);
    }
}

测试熔断功能

为了演示熔断功能,可以将服务端的sayHello方法改为抛出异常:

public String sayHello(String name) {
    if ("error".equals(name)) {
        throw new RuntimeException("Service error");
    }
    return "Hello, " + name;
}

当客户端调用sayHello方法并传入name参数为error时,服务端会抛出异常,触发熔断降级逻辑。

Sentinel对接Feign
Sentinel如何保护Feign客户端

Sentinel可以通过自定义的过滤器来保护Feign客户端。通过在SentinelFeignApplication.java中添加自定义的过滤器,可以在请求进入和离开Feign客户端时进行流量控制和熔断保护。

自定义过滤器

package com.example.sentinelfeign;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.datasource.PropertyManager;
import com.alibaba.csp.sentinel.datasource.callback.DataSourcePropertyListener;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.SentinelConfiguration;
import org.springframework.cloud.openfeign.FeignClientConfiguration;
import org.springframework.cloud.openfeign.support.FeignClientProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class SentinelFeignConfiguration {

    @Bean
    public DataSourcePropertyListener dataSourcePropertyListener() {
        return new DataSourcePropertyListener() {
            @Override
            public void onRefresh(String origin) {
                List<FlowRule> rules = new ArrayList<>();
                FlowRule rule = new FlowRule();
                rule.setResource("hello-service");
                rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
                rule.setCount(10);
                rules.add(rule);
                FlowRuleManager.loadRules(rules);
            }
        };
    }

    @Bean
    public SentinelConfiguration sentinelConfiguration() {
        TransportConfig.init();
        PropertyManager.addListener(dataSourcePropertyListener());
        return new SentinelConfiguration();
    }
}

配置Sentinel规则以实现熔断机制

通过DataSourcePropertyListener类可以监听Sentinel规则的变化,当规则发生变化时,可以动态更新Sentinel的规则:

@Bean
public DataSourcePropertyListener dataSourcePropertyListener() {
    return new DataSourcePropertyListener() {
        @Override
        public void onRefresh(String origin) {
            List<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule();
            rule.setResource("hello-service");
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            rule.setCount(10);
            rules.add(rule);
            FlowRuleManager.loadRules(rules);
        }
    };
}
实战案例解析
示例项目搭建

服务端代码

服务端提供一个简单的HelloService接口:

package com.example.sentinelfeign.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String sayHello(String name) {
        if ("error".equals(name)) {
            throw new RuntimeException("Service error");
        }
        return "Hello, " + name;
    }
}

Feign客户端代码

定义一个Feign客户端,调用服务端的sayHello方法:

package com.example.sentinelfeign.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "hello-service")
public interface HelloClient {
    @GetMapping("/hello")
    String sayHello(@RequestParam("name") String name);
}

控制器代码

创建一个控制器来调用Feign客户端:

package com.example.sentinelfeign.controller;

import com.example.sentinelfeign.service.HelloClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    private final HelloClient helloClient;

    public HelloController(HelloClient helloClient) {
        this.helloClient = helloClient;
    }

    @GetMapping("/hello")
    public String sayHello(@RequestParam("name") String name) {
        return helloClient.sayHello(name);
    }
}

配置文件

application.yml中配置服务端:

server:
  port: 8080

sentinel-feign-demo.yml中配置Sentinel规则:

sentinel:
  flow:
  rules:
    - resource: hello-service
      grade: QPS
      count: 10
      meterIntervalSec: 1
模拟高并发场景测试熔断功能

高并发场景模拟

使用工具如Apache JMeter或LoadRunner模拟高并发场景。

  1. 配置JMeter:在JMeter中配置HTTP请求,调用http://localhost:8080/hello?name=test
  2. 设置并发数:设置并发用户数为100,每个用户发送100次请求。
  3. 启动负载测试:启动JMeter,开始进行负载测试。

观察熔断效果

在高并发场景下,由于设置了Sentinel的QPS限制为10,当请求量超过10时,Sentinel会触发熔断降级逻辑,返回默认的错误信息。

故障注入

为了进一步测试熔断降级功能,可以在服务端代码中注入故障:

public String sayHello(String name) {
    if ("error".equals(name)) {
        throw new RuntimeException("Service error");
    }
    return "Hello, " + name;
}

当客户端调用sayHello方法并传入name参数为error时,服务端会抛出异常,触发熔断降级逻辑。

常见问题及解决方法
常见错误及解决方案
  1. Feign服务调用失败
    • 错误:Feign客户端调用服务时失败。
    • 原因:服务端接口定义不正确,或服务端未启动。
    • 解决方案:检查服务端接口定义是否正确,确保服务端已启动并正常运行。
  2. 熔断器状态转换失败
    • 错误:熔断器状态转换失败。
    • 原因:熔断器配置不正确,或服务端调用失败。
    • 解决方案:检查熔断器配置是否正确,确保服务端调用正常。
  3. Sentinel规则加载失败
    • 错误:Sentinel规则加载失败。
    • 原因:Sentinel规则配置文件错误,或Sentinel未启动。
    • 解决方案:检查Sentinel规则配置文件是否正确,确保Sentinel已启动。
  4. 熔断降级逻辑未触发
    • 错误:熔断降级逻辑未触发。
    • 原因:熔断器状态未转换到熔断状态。
    • 解决方案:检查熔断器状态是否正确,确保服务端调用失败。
运维监控建议
  1. 监控服务调用成功率
    • 监控指标:服务调用成功率。
    • 监控工具:使用Prometheus和Grafana监控服务调用成功率。
  2. 监控熔断器状态
    • 监控指标:熔断器状态。
    • 监控工具:使用Prometheus和Grafana监控熔断器状态。
  3. 监控服务端性能
    • 监控指标:服务端CPU使用率、内存使用率、响应时间等。
    • 监控工具:使用Prometheus和Grafana监控服务端性能。
  4. 监控Sentinel规则变化
    • 监控指标:Sentinel规则变化。
    • 监控工具:使用Prometheus和Grafana监控Sentinel规则变化。

通过以上监控建议,可以全面监控系统运行状态,及时发现并解决问题,确保系统稳定运行。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消