Sentinel -【SpringBoot、SpringCloud整合Sentinel】

Sentinel -【SpringBoot、SpringCloud整合Sentinel】

一、 Spring Boot项目中Sentinel的使用

1. 结合Sentinel核心库的使用

1.1 引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cspgroupId>
        <artifactId>sentinel-coreartifactId>
        <version>1.8.1version>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cspgroupId>
        <artifactId>sentinel-annotation-aspectjartifactId>
        <version>1.8.1version>
    dependency>
dependencies>

2.2 流控与熔断的示例

使用@SentinelResource注解的方式实现需要引入sentinel-annotation-aspectj依赖,还要配置SentinelResourceAspect的bean:

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author wyp
 */
@Configuration
public class SentinelResourceConfig {
    /**
     * 开启使用@SentinelResource
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

然后才能去用@SentinelResource注解配置规则:

package com.xc.demo.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wyp
 */
@RestController
@Slf4j
public class TestController {

    private static final String RESOURCE_NAME = "flowControl";
    private static final String DEGRADE_RESOURCE_NAME = "degrade";

    /**
     * spring 的初始化方法配置流控规则
     */
    @PostConstruct
    private void initFlowRules() {

        //流控规则
        List<FlowRule> rules = new ArrayList<>();
        //流控
        FlowRule flowRule = new FlowRule();
        //设置流控的资源
        flowRule.setResource(RESOURCE_NAME);
        //设置流控规则-QPS
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //设置受保护资源阈值-每秒只能访问一次
        flowRule.setCount(1);

        rules.add(flowRule);

        //加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }

    @RequestMapping("/flowControl")
    @SentinelResource(value = RESOURCE_NAME,blockHandler = "flowHandler",fallback = "flowFallback")
    public String flowControl() {
        if (Math.random()>0.7) {
            throw new RuntimeException("抛出运行异常");
        }
        String str = "flowControl";
        log.info("=====" + str + "=====");
        return str;
    }

    public String flowHandler(BlockException be) {
        be.printStackTrace();
        log.info("=====被流控了=====");
        return "被流控了";
    }

    public String flowFallback(Throwable e) {
        e.printStackTrace();
        log.info("=====抛出异常=====");
        return "抛出异常";
    }

    /**
     * spring 的初始化方法配置降级规则
     */
    @PostConstruct
    private void initDegradeRule() {
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule degradeRule = new DegradeRule();
        //设置熔断降级资源名
        degradeRule.setResource(DEGRADE_RESOURCE_NAME);
        //设置降级规则-异常数
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        //阈值计数,这里是触发熔断异常数- 2+1
        degradeRule.setCount(2);
        //可以触发熔断的最小请求数(在活动统计时间跨度内)-2
        degradeRule.setMinRequestAmount(2);
        //统计时间间隔,单位ms -1分钟
        degradeRule.setStatIntervalMs(60*1000);
        //熔断器打开时的恢复超时(以秒为单位)。超时后,断路器将转换为半开状态以尝试一些请求
        degradeRule.setTimeWindow(10);
        rules.add(degradeRule);
        //加载配置好的规则
        DegradeRuleManager.loadRules(rules);
    }

    @RequestMapping("/degrade")
    @SentinelResource(value = DEGRADE_RESOURCE_NAME,blockHandler = "degradeHandler")
    public String degrade() {
        if (Math.random() > 0.5) {
            throw new RuntimeException("运行异常");
        }
        String str = "degrade";
        log.info("=====" + str + "=====");
        return str;
    }

    public String degradeHandler(BlockException be) {
        be.printStackTrace();
        log.info("=====被熔断降级=====");
        return "被熔断降级";
    }
}

2. 结合Sentinel控制台的使用

前往:Sentinel 控制台

二、Spring Cloud Alibaba整合Sentinel

1. 引入依赖

spring cloud 项目中引入spring-cloud-starter-alibaba-sentinel依赖,整合了sentinel核心库和控制台。


<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

2. 配置

application配置文件中指定控制台的地址与端口号:

spring.cloud.sentinel.transport.dashboard=127.0.0.1:8858

spring.cloud.sentinel.transport的更多配置com.alibaba.cloud.sentinel.SentinelProperties.Transport类如下:


		/**
		 * Sentinel api 端口,默认值为 8719TransportConfig.SERVER_PORT 。
		 */
		private String port = SentinelConstants.API_PORT;

		/**
		 * Sentinel 仪表板地址,地址为空时不会尝试连接仪表板TransportConfig.CONSOLE_SERVER 。
		 */
		private String dashboard = "";

		/**
		 * 发送心跳间隔毫秒TransportConfig.HEARTBEAT_INTERVAL_MS 。
		 */
		private String heartbeatIntervalMs;

		/**
		 * 获取心跳客户端本地ip。如果没有配置客户端 ip,它将是本地主机的地址。该地址需要可以被sentinel客户端所访问到。
		 */
		private String clientIp;

3. 开始使用

为了方便,可创建统一异常处理BlockException异常的类实现BlockExceptionHandler接口。

package com.xc.consume.handler;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xc.consume.domain.SysResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 统一异常处理BlockException
 * @author wyp
 */
@Configuration
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    Logger log = LoggerFactory.getLogger(this.getClass());

    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {

        log.info("BlockExceptionHandler--全局BlockException处理=====" + e.getRule());

        SysResult sysResult = null;

        if (e instanceof FlowException) {
            sysResult = SysResult.fail(100,"流量控制");
        } else if (e instanceof DegradeException) {
            sysResult = SysResult.fail(101,"服务降级");
        } else if (e instanceof ParamFlowException) {
            sysResult = SysResult.fail(102,"热点参数限流");
        } else if (e instanceof SystemBlockException) {
            sysResult = SysResult.fail(103,"系统保护");
        } else if (e instanceof AuthorityException) {
            sysResult = SysResult.fail(104,"访问控制");
        }

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json");
        new ObjectMapper().writeValue(response.getWriter(),sysResult);
    }
}

有上述统一异常处理后,当不使用@SentinelResource注解时,遇到的BlockException都会去统一处理;当使用@SentinelResource注解指定资源名后,就算没有指定blockHandler属性,也不会再去统一处理了,控制台会打印异常信息。

你可能感兴趣的:(Spring,Cloud,Alibaba,sentinel,java,springcloud)