一、引言
小伙伴们应该都有过双11,双12等电商节的抢购经历吧?那么电商节当天的瞬时并发请求是非常非常巨量了,尽管做了很多性能优化及高可用等优化手段,仍然还是无法保证能马上处理所有的请求的,那么如何在高并发场景提供一项功能来对服务进行限流熔断降级呢?像是老牌的Hystrix,以及阿里开源的Sentinel都可以帮我们实现这一功能,这篇文章主要学习Sentinel如何使用以及和我们的工程进行整合。
PS:熔断、限流、降级其实体现在我们的工程流程中,就是当大量的请求到达服务端时,为了避免直接打崩我们的服务器,所采取的一种保护措施。我们通过熔断器组件直接返回一些信息,而不去真实的调用服务。
PS:说实话学这个的时候找了很多网上的教程搭建都不是很顺利,后来终于摸索出来了,如果小伙伴想跟着我的文章进行搭建的话,请一定不要漏一些步骤,遇到bug找资料都得找挺久还不一定有有效的解决方案,小伙伴们共勉~
二、下载Sentinel控制台
这里我就以windows的安装为例了,linux版本的安装大同小异,小伙伴们可以自己尝试动手玩一下。
下载地址:https://github.com/alibaba/Sentinel/releases
三、在工程中整合Sentinel
根据前面的文章,我们知道请求入口是OREDER-SERVER,所以这里我们的熔断器主要加在OREDER-SERVER工程中:
pom.xml
在pom.xml文件中增加以下依赖
<!--alibaba-sentinel熔断器核心依赖--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.2</version> </dependency> <!--alibaba-sentinel熔断器接入控制台的依赖--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>1.8.2</version> </dependency> <!--alibaba-sentinel熔断器注解方式实现的依赖--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-annotation-aspectj</artifactId> <version>1.8.2</version> </dependency>
配置熔断规则
方式一、手写熔断规则
/** * sentinel熔断示例【手写方式实现】 * * @author 有梦想的肥宅 * @date 2021/9/6 */ @RestController public class OrderSentinelHandWriteController { @Autowired private OutGdsApi outGdsApi; @RequestMapping("/orderSentinelHandWrite") public String showOrderInfo() { //1、根据资源orderSentinelHandWrite的熔断规则,判断时候可以执行try{}内部的业务代码 try (Entry entry = SphU.entry("orderSentinelHandWrite")) { return business();//执行业务逻辑 } catch (Exception e) { //2、当服务熔断时会抛出异常,进入此代码块,可以编写熔断后的逻辑 e.printStackTrace(); return "系统繁忙,请稍后重试!【Sentinel已经拦截请求~】【手写规则】"; } } /** * 定义熔断规则 * * @PostConstruct 此注解的含义是:本类构造方法执行结束后执行 */ @PostConstruct public void init() { //1.创建存放限流规则的集合 List<FlowRule> rules = new ArrayList<>(); //2.创建限流规则 FlowRule rule = new FlowRule(); //定义资源,表示Sentinel会对哪个资源生效 rule.setResource("orderSentinelHandWrite"); //定义限流的类型(此处使用QPS作为限流类型) rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //定义QPS每秒通过的请求数 rule.setCount(2); //3.将限流规则存放到集合中 rules.add(rule); //4.加载限流规则 FlowRuleManager.loadRules(rules); } //业务代码 private String business() { Map orderInfo = new HashMap(); orderInfo.put("orderId", 1); orderInfo.put("gdsInfo", outGdsApi.getGdsInfo("1")); return JSON.toJSONString(orderInfo); } }
方式二、注解方式设置资源,并在Sentinel控制台配置熔断规则
SentinelAspectConfiguration配置类
/** * Sentinel注解方式的配置 * * @author 有梦想的肥宅 * @date 2021/9/8 */ @Configuration public class SentinelAspectConfiguration { //定义一个SentinelResourceAspect类型的Bean交由Spring容器管理 @Bean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); } }
OrderSentinelAspectjController
/** * sentinel熔断示例【注解方式实现】 * * @author 有梦想的肥宅 * @date 2021/9/6 */ @RestController public class OrderSentinelAspectjController { @Autowired private OutGdsApi outGdsApi; //value:代表资源名称【在sentinel控制台设置】 blockHandler:设置熔断时的处理方法 @SentinelResource(value = "orderSentinelAspectj", blockHandler = "exceptionHandler") @RequestMapping("/orderSentinelAspectj") public String showOrderInfo() { Map orderInfo = new HashMap(); orderInfo.put("orderId", 1); orderInfo.put("gdsInfo", outGdsApi.getGdsInfo("1")); return JSON.toJSONString(orderInfo); } //限流降级的处理方法 private String exceptionHandler(BlockException e) { e.printStackTrace(); return "系统繁忙,请稍后重试!【Sentinel已经拦截请求~】【注解实现】"; } }
配置流控规则
启动项目进行测试