• 电商系统中进行流量控制


    1. 概述

    任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们要根据系统的处理能力对流量进行控制。

    流量控制的原理是监控应用的QPS或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性

    1. Sentinel简介

    sentinel是面向分布式服务框架的轻量级流量控制框架,主要以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来维护系统的稳定性

    1. Sentinel流量控制简介

    Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示

    流量控制有以下几个角度:

    • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;

    • 运行指标,例如 QPS、线程池、系统负载等;

    • 控制的效果,例如直接限流、冷启动、排队等。

    Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

    1. Sentinel流量控制功能的使用

    接下来,以b2b2c电商系统Javashop为例,具体说明Sentinel流量控制功能的使用

     

    1. pom.xml文件中引入依赖
     1    <dependency>
     2             <groupId>com.alibaba.csp</groupId>
     3             <artifactId>sentinel-transport-simple-http</artifactId>
     4             <version>1.8.0</version>
     5         </dependency>
     6         <dependency>
     7             <groupId>org.springframework.cloud</groupId>
     8             <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
     9             <version>0.2.0.RELEASE</version>
    10         </dependency>
    11         <dependency>
    12             <groupId>com.alibaba.csp</groupId>
    13             <artifactId>sentinel-spring-webmvc-adapter</artifactId>
    14             <version>1.8.0</version>
    15         </dependency>
    2.application.yml加入sentinel配置
     1 spring:
     2   cloud:
     3     sentinel:
     4       transport:
     5           #sentinel控制台地址(可有可无,不影响程序运行)
     6         dashboard: localhost:8080
     7 sentinel:
     8   #true:限制所有资源  false:只限制resources下定义的资源
     9   limit-all: true
    10   #限流阈值,每秒钟限制的请求数
    11   count: 5
    12   #要限流的资源(若限制所有资源,此项配置无效)
    13   resources:
    14     - 'GET:/regions/{id}/children'
    15     - 'GET:/regions/depth/{depth}'
    3.初始化限流规则
     1 @Component
     2 public class InitFlowRules implements ServletContextListener {
     3 
     4     @Autowired
     5     private RequestMappingHandlerMapping handlerMapping;
     6     @Autowired
     7     private SentinelConfig sentinelConfig;
     8 
     9     private final Logger logger = LoggerFactory.getLogger(this.getClass());
    10 
    11     @Override
    12     public void contextInitialized(ServletContextEvent sce) {
    13         List<String> resources = new ArrayList<>();
    14 
    15 
    16         //添加所有资源的规则
    17         if(sentinelConfig.isLimitAll()){
    18             Set<RequestMappingInfo> rmSet = handlerMapping.getHandlerMethods().keySet();
    19             for (RequestMappingInfo rm : rmSet) {
    20                 try{
    21                     String path = rm.getPatternsCondition().toString();
    22                     String method = rm.getMethodsCondition().toString();
    23                     path = path.replace("[", "").replace("]", "");
    24                     method = method.replace("[", "").replace("]", "");
    25                     String resource = method + ":" + path;
    26                     resources.add(resource);
    27                 }catch (Exception e){
    28                     e.printStackTrace();
    29                 }
    30             }
    31         }else {
    32             resources = sentinelConfig.getResources();
    33         }
    34 
    35         if(!StringUtil.isNotEmpty(resources)){
    36             return;
    37         }
    38 
    39         List<FlowRule> rules = new ArrayList<>();
    40         Integer count = sentinelConfig.getCount();
    41         for(String resource : resources){
    42             FlowRule rule = new FlowRule();
    43             rule.setResource(resource);
    44             rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    45             rule.setCount(count);
    46             rules.add(rule);
    47             logger.info(resource);
    48         }
    49         FlowRuleManager.loadRules(rules);
    50     }
    51 
    52     @Override
    53     public void contextDestroyed(ServletContextEvent sce) {
    54 
    55     }
    56 }
    4.配置限流拦截器
     1 @Configuration
     2 public class SentinelWebMvcConfiguration implements WebMvcConfigurer {
     3 
     4     @Autowired
     5     private SentinelConfig sentinelConfig;
     6 
     7 
     8     @Override
     9     public void addInterceptors(InterceptorRegistry registry) {
    10         SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
    11         //指定 请求方法 POST  GET 等等
    12         sentinelWebMvcConfig.setHttpMethodSpecify(true);
    13         //默认使用统一Web上下文   如果希望支持链路关系的流控策略则应该设置为false
    14         sentinelWebMvcConfig.setWebContextUnify(true);
    15         // 统一的 BlockException 处理  FlowException(BlockException) 会被 JVM 的 UndeclaredThrowableException 包裹一层  某种原因并不能捕获到异常
    16         sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
    17         // 用来标识来源 可针对性的对特定客户端的请求进行流控   limitApp
    18 //        sentinelWebMvcConfig.setOriginParser(request -> {
    19 //            String remoteAddr = "default";
    20 //            try {
    21 //                remoteAddr = getIpAddress(request);
    22 //            } catch (IOException e) {
    23 //                e.printStackTrace();
    24 //            }
    25 //            return remoteAddr;
    26 //        });
    27  //       sentinelWebMvcConfig.setOriginParser(request -> request.getParameter("app"));
    28 
    29         //对原始的URL进行处理,比如去掉锚点之类的    /foo/bar?a=3#title  ->   /foo/bar?a=3
    30 //        sentinelWebMvcConfig.setUrlCleaner( );
    31         registry.addInterceptor(new SentinelWebInterceptor(sentinelWebMvcConfig)).addPathPatterns("/**");
    32     }
    33 
    34 }
    5.限流全局异常处理
     1 public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
     2 
     3     @Override
     4     public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
     5         httpServletResponse.setStatus(500);
     6         httpServletResponse.setHeader("Content-Type", "application/json;charset=utf-8");
     7         httpServletResponse.getWriter().print("{"code":"500","message":"请求被限制,请稍后重试"}");
     8         httpServletResponse.getWriter().flush();
     9     }
    10 }
  • 相关阅读:
    es6
    vue-router
    vue-lazyload
    java-number2
    echart事件
    weui了解
    java-number
    Java判断语句
    java 循环控制
    The access type for the readers of the blog.
  • 原文地址:https://www.cnblogs.com/javashop-docs/p/14272779.html
Copyright © 2020-2023  润新知