java流控框架_电商系统中进行流量控制

概述

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

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

Sentinel简介

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

Sentinel流量控制简介

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

2124c2949416778f94dee63397b0ec09.png

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

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

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

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

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

Sentinel流量控制功能的使用

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

1. pom.xml文件中引入依赖

1

2 com.alibaba.csp

3 sentinel-transport-simple-http

4 1.8.0

5

6

7 org.springframework.cloud

8 spring-cloud-starter-alibaba-sentinel

9 0.2.0.RELEASE

10

11

12 com.alibaba.csp

13 sentinel-spring-webmvc-adapter

14 1.8.0

15

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 @Component2 public class InitFlowRules implementsServletContextListener {3

4 @Autowired5 privateRequestMappingHandlerMapping handlerMapping;6 @Autowired7 privateSentinelConfig sentinelConfig;8

9 private final Logger logger = LoggerFactory.getLogger(this.getClass());10

11 @Override12 public voidcontextInitialized(ServletContextEvent sce) {13 List resources = new ArrayList<>();14

15

16 //添加所有资源的规则

17 if(sentinelConfig.isLimitAll()){18 Set 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 rules = new ArrayList<>();40 Integer count =sentinelConfig.getCount();41 for(String resource : resources){42 FlowRule rule = newFlowRule();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 @Override53 public voidcontextDestroyed(ServletContextEvent sce) {54

55 }56 }

4.配置限流拦截器

1 @Configuration2 public class SentinelWebMvcConfiguration implementsWebMvcConfigurer {3

4 @Autowired5 privateSentinelConfig sentinelConfig;6

7

8 @Override9 public voidaddInterceptors(InterceptorRegistry registry) {10 SentinelWebMvcConfig sentinelWebMvcConfig = newSentinelWebMvcConfig();11 //指定 请求方法 POST GET 等等

12 sentinelWebMvcConfig.setHttpMethodSpecify(true);13 //默认使用统一Web上下文 如果希望支持链路关系的流控策略则应该设置为false

14 sentinelWebMvcConfig.setWebContextUnify(true);15 //统一的 BlockException 处理 FlowException(BlockException) 会被 JVM 的 UndeclaredThrowableException 包裹一层 某种原因并不能捕获到异常

16 sentinelWebMvcConfig.setBlockExceptionHandler(newDefaultBlockExceptionHandler());17 //用来标识来源 可针对性的对特定客户端的请求进行流控 limitApp18 //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=330 //sentinelWebMvcConfig.setUrlCleaner( );

31 registry.addInterceptor(new SentinelWebInterceptor(sentinelWebMvcConfig)).addPathPatterns("/**");32 }33

34 }

5.限流全局异常处理

1 public class DefaultBlockExceptionHandler implementsBlockExceptionHandler {2

3 @Override4 public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throwsException {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 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值