springboot项目引入Sentinel熔断

news2024/9/21 14:43:34

本文是springboot项目+nacos进行引入,sentiel需自行按照部署

1.springboot包要是2.2.5或以上

<dubbo.version>2.7.7</dubbo.version>
        <spring-boot.version>2.2.5.RELEASE</spring-boot.version>
        <chainwork-boot.version>1.0.5-SNAPSHOT</chainwork-boot.version>
        <nacos.version>0.2.7</nacos.version>
        <spring-cloud-nacos-config.version>2.2.5.RELEASE</spring-cloud-nacos-config.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <spring-cloud-nacos-discovery.version>2.2.5.RELEASE</spring-cloud-nacos-discovery.version>
<!--       
        <arthas.version>3.4.3</arthas.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <nacos-client.version>1.4.1</nacos-client.version>
        <redisson.version>3.13.6</redisson.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>

2.项目后端需依赖包

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <!-- Sentinel数据源之 Nacos -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.1.Final</version>
        </dependency>

3.项目前端需依赖包

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.1.Final</version>
        </dependency>

4.后端 bootstrap.yml需配置

#server:
#  port: 8888
spring:
  #  application:
  #    name: test-server
  main:
    allow-bean-definition-overriding: true
  cloud:
    sentinel:
      datasource:
        # 流控规则,名字任意
        ds-flow:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-flow-rules
            ## 配置存储的格式
            data-type: json
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            rule-type: flow
        ## 配置降级规则,名字任意
        ds-degrade:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-degrade-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            ## rule-type设置对应得规则类型,总共七大类型,在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中有体现
            rule-type: degrade
        ## 配置系统规则,名字任意
        ds-system:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-system-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            rule-type: system
    nacos:
      discovery:
        server-addr: 11.11.11.11:8848
      #        group: lj
      config:
        # 配置中心地址配置
        server-addr: 11.11.11.11:8848
        # 定义配置文件后缀为.properties, dataId=${spring.application.name}-${spring.profiles.active}.properties
        file-extension: properties
        group: prd
        # 定义配置中心分组:
        shared-configs[0]: #多个从0开始递增  扩展的是数字越大的优先级越高
          data-id: global-server-prd.properties #配置文件名
          group: DEFAULT_GROUP #分组名称
        #          refresh: true #配置扩展属性动态刷新
        shared-configs[1]:
          data-id: test-service-prd.properties
          #          data-id: test-service-test-sit.properties
          group: prd
  #          refresh: true
  profiles:
    # 定义环境为dev
    active: prd

5.前端 bootstrap.yml需配置

server:
  #  port: 8888
  servlet:
    context-path: /test-web
spring:
  #  application:
  #    name: test-web
  main:
    allow-bean-definition-overriding: true
  cloud:
    sentinel:
      #      eager: true
      #      filter:
      #        enabled: false
      #      transport:
      #        dashboard: 127.0.0.1:12180
      #      web-context-unify: false
      datasource:
        # 流控规则,名字任意
        ds-flow:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-flow-rules
            ## 配置存储的格式
            data-type: json
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            rule-type: flow
        ## 配置降级规则,名字任意
        ds-degrade:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-degrade-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            ## rule-type设置对应得规则类型,总共七大类型,在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中有体现
            rule-type: degrade
        ## 配置系统规则,名字任意
        ds-system:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-system-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            rule-type: system
    nacos:
      discovery:
        server-addr: 11.11.11.11:8848
      config:
        # 配置中心地址配置
        
        server-addr: 11.11.11.11:8848
        # 定义配置文件后缀为.properties, dataId=${spring.application.name}-${spring.profiles.active}.properties
        file-extension: properties
        #        group: sit
        # 定义配置中心分组:
        shared-configs[0]: #多个从0开始递增 扩展的是数字越大的优先级越高
          data-id: global-web-prd.properties #配置文件名
          group: DEFAULT_GROUP #分组名称
          refresh: true #配置扩展属性动态刷新
        shared-configs[1]:
          data-id: test-web-prd.properties
          group: prd
#          refresh: true

6.后端引入异常处理及配置类


import cn.hutool.json.JSONUtil;
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.sinoservices.beans.ResultMessage;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

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

/**
 * sentinel异常处理程序
 */
@Configuration
public class SentinelCustomBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        ResultMessage resultMessage = new ResultMessage();

        if (e instanceof FlowException) {
            // 限流
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
        } else if (e instanceof DegradeException) {
            // 熔断
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求在排队,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
        } else if (e instanceof ParamFlowException) {
            // 参数热点
            resultMessage.setSuccess(false);
            resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
        } else if (e instanceof SystemBlockException) {
            //系统保护
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
        } else if (e instanceof AuthorityException) {

        }
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONUtil.toJsonStr(resultMessage));
    }
}
**
 * 常量
 *
 * @description: 全局异常处理
 */
@Slf4j
@ControllerAdvice
public class TestServerGlobalExceptionHandler {

    /**
     * validator 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Message handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("参数校验异常:{},{}", e.getMessage(), e);
        FieldError fieldError = e.getBindingResult().getFieldError();

        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(fieldError.getDefaultMessage());
        //message.addMessage(fieldError.getField() + fieldError.getDefaultMessage());
        return message;
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public Message handleFeignException(IllegalArgumentException e) {
        log.error("IllegalArgumentException异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(e.getMessage());
        return message;
    }

    @ExceptionHandler(FeignException.class)
    @ResponseBody
    public ResultMessage handleFeignException(FeignException e) {
        log.error("openFeign异常:{},{}", e.getMessage(), e);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setSuccess(false);
        resultMessage.setMessage(e.getMessage());
        resultMessage.setErrorDetailMessage(e.getMessage());
        return resultMessage;
    }

    

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Message handleException(Exception e) {
        log.error("接口异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(e.getMessage());
        return message;
    }

    @ExceptionHandler(StaleObjectStateException.class)
    @ResponseBody
    public Message versionErrorException(Exception e) {
        log.error("数据库修改版本冲突异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage("数据版本冲突,请刷新后再操作");
        return message;
    }

    @ExceptionHandler(BlockException.class)
    @ResponseBody
    public ResultMessage sentinelBlockHandler(BlockException e) {
        log.error("sentinelBlock异常:{},{}", e.getMessage(), e);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setSuccess(false);
        resultMessage.setMessage(e.getRule() + "系统繁忙,请稍后处理");
        resultMessage.setErrorDetailMessage(e.getRule() + "系统繁忙,请稍后处理");
        return resultMessage;
    }


}

import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.SentinelProperties.Filter;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Optional;

@Configuration(
        proxyBeanMethods = false
)
@ConditionalOnClass({SentinelWebInterceptor.class})
@EnableConfigurationProperties({SentinelProperties.class})
public class SentinelWebAutoConfiguration implements WebMvcConfigurer {
    private static final Logger log = LoggerFactory.getLogger(SentinelWebAutoConfiguration.class);
    @Autowired
    private SentinelProperties properties;
    @Autowired
    private Optional<UrlCleaner> urlCleanerOptional;
    @Autowired
    private Optional<BlockExceptionHandler> blockExceptionHandlerOptional;
    @Autowired
    private Optional<RequestOriginParser> requestOriginParserOptional;
    @Autowired
    private Optional<SentinelWebInterceptor> sentinelWebInterceptorOptional;

    public SentinelWebAutoConfiguration() {
    }

    public void addInterceptors(InterceptorRegistry registry) {
        if (this.sentinelWebInterceptorOptional.isPresent()) {
            Filter filterConfig = this.properties.getFilter();
            registry.addInterceptor((HandlerInterceptor) this.sentinelWebInterceptorOptional.get()).order(filterConfig.getOrder()).addPathPatterns(filterConfig.getUrlPatterns());
            log.info("[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", filterConfig.getUrlPatterns());
        }
    }

    @Bean
    public SentinelWebInterceptor sentinelWebInterceptor(SentinelWebMvcConfig sentinelWebMvcConfig) {
        return new SentinelWebInterceptor(sentinelWebMvcConfig);
    }

    @Bean
    public SentinelWebMvcConfig sentinelWebMvcConfig() {
        SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
        sentinelWebMvcConfig.setHttpMethodSpecify(this.properties.getHttpMethodSpecify());
        sentinelWebMvcConfig.setWebContextUnify(this.properties.getWebContextUnify());
        if (this.blockExceptionHandlerOptional.isPresent()) {
            this.blockExceptionHandlerOptional.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler);
        } else if (StringUtils.hasText(this.properties.getBlockPage())) {
            sentinelWebMvcConfig.setBlockExceptionHandler((request, response, e) -> {
                response.sendRedirect(this.properties.getBlockPage());
            });
        } else {
            sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
        }

        this.urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner);
        this.requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser);
        return sentinelWebMvcConfig;
    }
}

7.前端引入异常处理及配置类



import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

/**
 * @description:
 * @author: John.Zhang
 * @date: 2023年03月02日
 * @version: 1.0.0
 */

@Component
@RefreshScope
@Data
public class FilterAssignUrlConfig {

    /**
     * 忽略静态资源
     */
    @Value("${request.ignore.requestSuffix}")
    public  String ignoreRequestSuffix;


    /**
     * 忽略登录请求
     */
    @Value("${request.ignore.requestUrl}")
    public  String ignoreRequestUrl;

}
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @description:
 */
@Configuration
public class FilterContextConfig {

    @Autowired
    private SentinelCustomFilter sentinelCustomFilter;

    @Autowired
    private FilterAssignUrlConfig filterAssignUrlConfig;


    /**
     * https://github.com/alibaba/Sentinel/issues/1213
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(sentinelCustomFilter);
        registration.addUrlPatterns("/*");
        registration.addInitParameter("excludedUris", filterAssignUrlConfig.getIgnoreRequestUrl());
        registration.addInitParameter("excludedRequestFileExtension", filterAssignUrlConfig.getIgnoreRequestSuffix());
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelCustomFilter");
        registration.setOrder(1);
        return registration;
    }


}
import com.alibaba.csp.sentinel.*;
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig;
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
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.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Component
public class SentinelCustomFilter implements Filter {

    /**
     * Specify whether the URL resource name should contain the HTTP method prefix (e.g. {@code POST:}).
     */
    public static final String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY";
    /**
     * If enabled, use the default context name, or else use the URL path as the context name,
     * {@link WebServletConfig#WEB_SERVLET_CONTEXT_NAME}. Please pay attention to the number of context (EntranceNode),
     * which may affect the memory footprint.
     *
     * @since 1.7.0
     */
    public static final String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY";

    private final static String COLON = ":";

    private boolean httpMethodSpecify = false;
    private boolean webContextUnify = true;
    private String[] excludedUris;
    private String excludedRequestFileExtension;


    @Override
    public void init(FilterConfig filterConfig) {
        String param = filterConfig.getInitParameter("excludedUris");
        if (StringUtils.isNotBlank(param)) {
            this.excludedUris = param.split(",");
        }

        String excludedRequestFileExtension = filterConfig.getInitParameter("excludedRequestFileExtension");
        if (StringUtils.isNotBlank(excludedRequestFileExtension)) {
            this.excludedRequestFileExtension = excludedRequestFileExtension;
        }

        httpMethodSpecify = Boolean.parseBoolean(filterConfig.getInitParameter(HTTP_METHOD_SPECIFY));
        if (filterConfig.getInitParameter(WEB_CONTEXT_UNIFY) != null) {
            webContextUnify = Boolean.parseBoolean(filterConfig.getInitParameter(WEB_CONTEXT_UNIFY));
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest sRequest = (HttpServletRequest) request;
        Entry urlEntry = null;
        String target = null;
        boolean reqFlag = false;
        try {
            target = FilterUtil.filterTarget(sRequest);
            // 定义表示变量 并验证用户请求URI 是否包含不过滤路径
            for (String uri : excludedUris) {
                if (target.equals(uri)) {
                    reqFlag = true;
                }
                if (target.indexOf(".") > -1) {
                    if (excludedRequestFileExtension.contains(target.substring(target.lastIndexOf(".") + 1, target.length()))) {
                        reqFlag = true;
                    }
                }

            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {
            if (!reqFlag) {
                // Clean and unify the URL.
                // For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
                // the amount of context and resources will exceed the threshold.
                UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
                if (urlCleaner != null) {
                    target = urlCleaner.clean(target);
                }

                // If you intend to exclude some URLs, you can convert the URLs to the empty string ""
                // in the UrlCleaner implementation.
                if (!StringUtil.isEmpty(target)) {
                    // Parse the request origin using registered origin parser.
                    String origin = parseOrigin(sRequest);
                    String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
                    ContextUtil.enter(contextName, origin);

                    if (httpMethodSpecify) {
                        // Add HTTP method prefix if necessary.
                        String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + COLON + target;
                        urlEntry = SphU.entry(pathWithHttpMethod, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                    } else {
                        urlEntry = SphU.entry(target, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                    }
                }
            }
            chain.doFilter(request, response);
        } catch (BlockException e) {
            HttpServletResponse sResponse = (HttpServletResponse) response;
            HttpServletRequest sRequest2 = (HttpServletRequest) request;
            // Return the block page, or redirect to another URL.
            // WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
            StringBuffer url = sRequest2.getRequestURL();
            if ("GET".equals(sRequest2.getMethod()) && StringUtil.isNotBlank(sRequest2.getQueryString())) {
                url.append("?").append(sRequest2.getQueryString());
            }
            ResultMessage resultMessage = new ResultMessage();

            if (e instanceof FlowException) {
                // 限流
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
            } else if (e instanceof DegradeException) {
                // 熔断
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统请求在排队,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
            } else if (e instanceof ParamFlowException) {
                // 参数热点
                resultMessage.setSuccess(false);
                resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            } else if (e instanceof SystemBlockException) {
                //系统保护
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
            }

            if (StringUtil.isBlank(WebServletConfig.getBlockPage())) {
                sResponse.setStatus(WebServletConfig.getBlockPageHttpStatus());
                sResponse.setCharacterEncoding("utf-8");
                sResponse.setHeader("Content-Type", "application/json;charset=utf-8");
                PrintWriter out = sResponse.getWriter();
                String blockMsg = JSON.toJSONString(resultMessage);
                out.print(blockMsg);
                out.flush();
                out.close();
            } else {
                String redirectUrl = WebServletConfig.getBlockPage() + "?http_referer=" + url.toString();
                sResponse.sendRedirect(redirectUrl);
            }
        } catch (IOException | ServletException | RuntimeException e2) {
            Tracer.traceEntry(e2, urlEntry);
            throw e2;
        } finally {
            if (urlEntry != null) {
                urlEntry.exit();
            }
            ContextUtil.exit();
        }
    }

    private String parseOrigin(HttpServletRequest request) {
        RequestOriginParser originParser = WebCallbackManager.getRequestOriginParser();
        String origin = EMPTY_ORIGIN;
        if (originParser != null) {
            origin = originParser.parseOrigin(request);
            if (StringUtil.isEmpty(origin)) {
                return EMPTY_ORIGIN;
            }
        }
        return origin;
    }

    @Override
    public void destroy() {

    }

    private static final String EMPTY_ORIGIN = "";

}


import cn.hutool.json.JSONUtil;
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 org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

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

/**
 * sentinel异常处理程序
 */
@Configuration
public class SentinelCustomBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        ResultMessage resultMessage = new ResultMessage();

        if (e instanceof FlowException) {
            // 限流
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
        } else if (e instanceof DegradeException) {
            // 熔断
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求在排队,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
        } else if (e instanceof ParamFlowException) {
            // 参数热点
            resultMessage.setSuccess(false);
            resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
        } else if (e instanceof SystemBlockException) {
            //系统保护
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
        } else if (e instanceof AuthorityException) {

        }
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONUtil.toJsonStr(resultMessage));
    }
}

8.nacos需增加对应配置

spring.cloud.sentinel.transport.dashboard=11.111.1.112:11180
spring.cloud.sentinel.web-context-unify=false
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.filter.enabled=false
feign.sentinel.enabled=true

9.启动项目后就可在sentiel中进行规则配置

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2111617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.Net C#检验科LIS系统成品源码 ,LIS 系统与 HIS 系统的连接方式详解

目录 系统定义与功能 应用特点 检验科 LIS 系统与 HIS 系统的连接方式 1、接口设计与数据交换 2、网络架构 3、数据格式与标准化 4、信息共享与协同工作 5、数据安全与隐私保护 6、技术支持与维护 LIS系统成品源码 总结 系统定义与功能 LIS系统&#xff0c;全称为实验…

python tkinter 简介

ttk模块是tkinter模块中非常重要的模块&#xff0c;相当于升级版的tkinter模块。 ttk模块包含18个组件&#xff0c;其中12个组件在tkinter模块中已经存在。这12个模块分别为Button&#xff08;按钮&#xff09;​、Checkbutton&#xff08;复选框&#xff09;​、Entry&#x…

OrangePi AIpro 香橙派 昇腾 Ascend C 算子开发 与 调用 - 通过aclnn调用的方式调用AddCustom算子

OrangePi AIpro 香橙派 昇腾 Ascend C 算子开发 与 调用 通过aclnn调用的方式调用 - AddCustom算子 - 单算子API执行(aclnn) 多种算子调用方式 *开发时间使用场景调用方式运行硬件基于Kernel直调工程&#xff08;快速&#xff09;少单算子调用&#xff0c;快速验证算法逻辑IC…

MySQL复习3

视图 视图&#xff08;view&#xff09;是一种虚拟存在的表&#xff0c;是一个逻辑表&#xff0c;本省没有数据&#xff0c;内容由查询定义。 基表&#xff1a;用来创建视图的表叫做基表 通过视图&#xff0c;我们可以查看基表的部分数据。视图数据来自定义视图的查询中使用…

[Go]-抢购类业务方案

文章目录 要点&#xff1a;1. 抢购/秒杀业务的关键挑战2. 技术方案3.关键实现点4.性能优化建议5.其他考虑因素 细节拆分&#xff1a;1. **高并发处理**2.**限流与防护**3.**库存控制**4. **异步处理**5. **数据一致性**6. **常用架构设计**7. **代码示例**8. 进一步优化9. 注意…

鸿蒙(API 12 Beta6版)图形加速【OpenGL ES平台内插模式】超帧功能开发

超帧内插模式是利用相邻两个真实渲染帧进行超帧计算生成中间的预测帧&#xff0c;即利用第N-1帧和第N帧真实渲染帧预测第N-0.5帧预测帧&#xff0c;如下图所示。由于中间预测帧的像素点通常能在前后两帧中找到对应位置&#xff0c;因此内插模式的预测帧效果较外插模式更优。由于…

android studio 模拟器 loadlibrary failed with 126:找不到指定的模块

loadlibrary failed with 126:找不到指定的模块 解决方法 解决方法&#xff1a;设备管理器-> 显示适配器-> 禁用 AMD Redeon 重启AndroidStudio

【学习笔记】 陈强-机器学习-Python-Ch14 支持向量机

系列文章目录 监督学习&#xff1a;参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归&#xff08;SAheart.csv&#xff09; 【学习笔记】 陈强-机器学习-Python-…

示波器在嵌入式中的作用和使用

你是否在开发嵌入式系统时&#xff0c;遇到过调试电路和信号分析的困难&#xff1f; 在嵌入式开发中&#xff0c;硬件调试和信号分析是必不可少的环节&#xff0c;而示波器作为一种强大的工具&#xff0c;能够帮助我们深入了解信号特性并解决难题。那么&#xff0c;如何正确使用…

Aigtek功率放大器可以驱动哪些传感器设备

功率放大器是一种电子设备&#xff0c;主要用于将输入信号增强到更高的功率级别并驱动各种负载。在传感器应用中&#xff0c;功率放大器可以用来驱动多种传感器设备&#xff0c;下面将介绍几个常见的应用场景。 光学传感器&#xff1a;光学传感器是一类基于光学原理工作的传感器…

Django发送邮件

【图书介绍】《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 Django 5框架Web应用开发_夏天又到了的博客-CSDN博客 本文学习怎么使用Django发送邮件。 尽管使用Python的smtplib模块发送电子邮件…

Flutter集成Firebase中的Remote Config

远程配置&#xff08;Remote Config&#xff09;的功能 动态配置参数&#xff1a;Remote Config 允许您在不更新应用程序的情况下&#xff0c;实时更改应用程序的参数&#xff0c;如文本、颜色、布尔值等条件化参数&#xff1a;您可以基于用户的特定条件&#xff08;例如用户地…

ADC——模数转换器

一、转换流程 在处理器中主要进行ADC 1、AD转换流程 &#xff1a;采样、保持、量化、编码 通过比较器获得的电信号转换数字信号&#xff0c;根据自己需求&#xff0c;如果要求速率就可以使用较多的比较器&#xff0c;不要求速率考虑成本就可以使用较少的比较器&#xff0c;将最…

【Oracle篇】全面理解优化器和SQL语句的解析步骤(含执行计划的详细分析和四种查看方式)(第二篇,总共七篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

828华为云征文 | Flexus X实例CPU、内存及磁盘性能实测与分析

引言 随着云计算的普及&#xff0c;企业对于云资源的需求日益增加&#xff0c;而选择一款性能强劲、稳定性高的云实例成为了关键。华为云Flexus X实例作为华为云最新推出的高性能实例&#xff0c;旨在为用户提供更强的计算能力和更高的网络带宽支持。最近华为云828 B2B企业节正…

AFSim仿真系统---向导参考指南 (1)

向导参考指南 向导参考指南列出了包含在向导中的功能&#xff0c;并按各种类别进行了组织。 启动 命令行选项 1 命令行参数 - 向导 用法&#xff1a; wizard.exe [ <file_name.txt> ][ <project_file.afproj> ]{ -console } <file_name1.txt> <file_n…

QT:QWidget 控件属性的介绍

控件属性介绍 &#x1f334;enabled 状态属性&#x1f334;geometry 几何属性示例一&#xff1a;改变控件尺寸示例二&#xff1a;更变控件位置window frame 的影响 &#x1f334;windowTitle 窗口标题&#x1f334;windowIcon 窗口图标&#x1f334; qrc机制&#x1f334;windo…

DevExpress WinForms v24.1新版亮点:功能区、数据编辑器全新升级

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

CMAQ 5.4 输入与输出数据

CMAQ 5.4 输入与输出数据 参考 CMAQ输入文件.https://github.com/USEPA/CMAQ/blob/main/DOCS/Users_Guide/CMAQ_UG_ch04_model_inputs.md CMAQ输出文件.https://github.com/USEPA/CMAQ/blob/main/DOCS/Users_Guide/CMAQ_UG_ch07_model_outputs.md 目录 文章目录 CMAQ 5.4 输…

企业如何组建安全稳定的跨国通信网络?

组建一个安全稳定的跨国通信网络对于现代企业来说至关重要&#xff0c;尤其是当企业在全球范围内运营时。以下是一些关键步骤和考虑因素&#xff1a; 需求分析&#xff1a; 确定企业的具体通信需求&#xff0c;包括带宽要求、延迟敏感度、数据类型&#xff08;如语音、视频、文…