Sentinel实战(待完善)

目录

服务雪崩

什么是服务雪崩

服务不可用原因

解决方案

技术选型对比

Sentinel

介绍

优点

核心概念

资源

规则

代码实战

API实现

@SentinelResource注解实现

Sentinel控制台

启动控制台服务

java应用接入控制台

微服务接入Sentinel


服务雪崩

什么是服务雪崩

在服务调用链路中, 服务提供者不可用, 导致服务调用者不可用, 间接让上上游也不可用, 这个不可用逐渐放大的过程, 叫做服务雪崩

服务不可用原因

  • 内存泄漏
  • 大流量请求, 超过正常承受qps
  • 缓存击穿, 大量直接打到数据库
  • 硬件损坏

解决方案

  1. 超时机制

  2. 限流

  3. 资源隔离(线程池/信号量隔离)

  4. 熔断降级

技术选型对比

Sentinel

介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

官方文档: https://sentinelguard.io/zh-cn/docs/introduction.html

优点

  • 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
  • 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。

核心概念

资源

资源可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。

规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。一个资源可以对应多个规则, 一个规则只能对应一个资源.

代码实战

API实现

  1. 引入maven依赖
XML 复制代码
<dependency>
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-core</artifactId>
     <version>1.8.6</version>
</dependency>
  1. 接口实现
java 复制代码
@RestController
@Slf4j
public class HelloController {

    // 定义资源名称
    private static final String RESOURCE_NAME = "HelloWorld";

    @RequestMapping(value = "/hello")
    public String hello() {
        // try catch包起来的代码块 就是资源
        try (Entry entry = SphU.entry(RESOURCE_NAME)) {
            // 被保护的逻辑
            log.info("hello world");
            return "hello world";
        } catch (BlockException ex) {
            // 自定义流控逻辑
            log.info("blocked!");
            return "被流控了";
        }
    }
    /**
     * 定义流控规则
     */
    @PostConstruct
    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        //设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则 QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值, qps>1 就被流控
        rule.setCount(1);
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }
}

存在缺点: 代码侵入太强, 不够灵活

@SentinelResource注解实现

  1. 引入pom依赖, sentinel核心jar和切面jar
XML 复制代码
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.6</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.6</version>
        </dependency>
  1. 注入切面类
java 复制代码
@Configuration
public class SentinelAspectConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}
  1. 设置流控规则注解, 注解定义资源以及降级逻辑
java 复制代码
    @PostConstruct
    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        //设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则 QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值
        rule.setCount(3);
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }

    @SentinelResource(value = RESOURCE_NAME,
            blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class,
            fallback = "fallbackException",fallbackClass = ExceptionUtil.class)
    @RequestMapping("/hello2")
    public String hello2() {
        int i = 1 / 0;
        return "helloworld ";
    }
java 复制代码
public class ExceptionUtil {

    public static String fallbackException(Throwable t){
        return "===被异常降级啦===";
    }

    public static String handleException(BlockException ex){
        return "===被限流啦===";
    }
}

Sentinel控制台

启动控制台服务

官方文档:https://sentinelguard.io/zh-cn/docs/dashboard.html

  1. 下载控制台

https://github.com/alibaba/Sentinel/releases/download/1.8.7/sentinel-dashboard-1.8.7.jar

  1. 启动控制台

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar

  1. 登录控制台

访问http://localhost:8080/#/login ,默认用户名密码: sentinel/sentinel

java应用接入控制台

  1. 引入sentinel通信jar
XML 复制代码
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>1.8.6</version>
        </dependency>
  1. java应用增加启动参数, 启动服务

-Dproject.name=kk-sentinel-demo -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.api.port=8719

  1. 访问流控接口http://localhost:8800/hello, 登录控制台检查
  1. 控制台修改流控规则, 接口测试, 实时生效
  1. get接口查看流控规则, url = http://localhost:8720/getRules?type=flow

微服务接入Sentinel

  1. 引入pom依赖
XML 复制代码
        <!--sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>


        <!-- 对外暴露的 Endpoint -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  1. 修改yml配置
cs 复制代码
server:
  port: 8800

feign:
  sentinel:
    enabled: true  #开启Sentinel 对 Feign 的支持

spring:
  application:
    name: mall-user
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080
        # 指定应用与Sentinel控制台交互的端口,应用会起一个HttpServer占用该端口
        # port: 8719

#暴露actuator端点   http://localhost:8800/actuator/sentinel
management:
  endpoints:
    web:
      exposure:
        include: '*'
  1. 对URL流控
java 复制代码
    // 对URL流控
    @RequestMapping("/info/{id}")
    @SentinelResource(value = "userinfo", blockHandler = "handleException")
    public R info(@PathVariable("id") Integer id){
        UserEntity user = userService.getById(id);
        if(id==4){
            throw new IllegalArgumentException("异常参数");
        }

        return R.ok().put("user", user);
    }

    // 对子方法流控
    @SentinelResource(value = "getUser",blockHandler = "handleException")
    public UserEntity getById(Integer id) {
        return userDao.getById(id);
    }
  1. 接入openFeign 熔断降级
java 复制代码
@FeignClient(value = "mall-order",path = "/order",fallbackFactory = FallbackOrderFeignServiceFactory.class)
public interface OrderFeignService {

    @RequestMapping("/findOrderByUserId/{userId}")
    public R findOrderByUserId(@PathVariable("userId") Integer userId);
}



@Component
public class FallbackOrderFeignServiceFactory implements FallbackFactory<OrderFeignService> {
    @Override
    public OrderFeignService create(Throwable throwable) {
        return new OrderFeignService() {
            @Override
            public R findOrderByUserId(Integer userId) {
                return R.error(-1,"=======服务降级了========");
            }
        };
    }
}
相关推荐
保持学习ing4 分钟前
day1--项目搭建and内容管理模块
java·数据库·后端·docker·虚拟机
京东云开发者15 分钟前
Java的SPI机制详解
java
超级小忍38 分钟前
服务端向客户端主动推送数据的几种方法(Spring Boot 环境)
java·spring boot·后端
程序无bug42 分钟前
Spring IoC注解式开发无敌详细(细节丰富)
java·后端
小莫分享44 分钟前
Java Lombok 入门
java
程序无bug44 分钟前
Spring 对于事务上的应用的详细说明
java·后端
食亨技术团队1 小时前
被忽略的 SAAS 生命线:操作日志有多重要
java·后端
苦学编程的谢1 小时前
Maven
java·maven·intellij-idea
考虑考虑1 小时前
Maven 依赖范围(Scope)
java·后端·maven
张小洛1 小时前
Spring AOP 设计解密:代理对象生成、拦截器链调度与注解适配全流程源码解析
java·后端·spring·spring aop·aop