视频链接:2020最新版SpringCloud框架开发教程-周阳
文章源码:https://github.com/geyiwei-suzhou/cloud2020/
cloudalibaba-consumer-nacos-order84模块
无配置
根据上一篇文章:SpingCloud 2020微服务教程【52】Sentinel服务熔断模块搭建 在无其他配置的情况下,访问:http://localhost:84/consumer/fallback/1 order84模块依次调用payment9003、payment9004 模块,访问:http://localhost:84/consumer/fallback/4,http://localhost:84/consumer/fallback/100 因为没有任何配置,接口直接返回错误页面给客户,不够友好
配置fallback
修改方法:com.antherd.springcloud.alibaba.controller.CircleBreakerController.fallback 的注解
@SentinelResource(value = "fallback", fallback = "handlerFallback") // fallback只负责业务异常
并添加兜底方法 handlerFallback:
// 本例是fallback
public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
Payment payment = new Payment(id, null);
return new CommonResult(444, "兜底异常handlerFallback,exception内容:" + e.getMessage(), payment);
}
访问:http://localhost:84/consumer/fallback/4,http://localhost:84/consumer/fallback/100 发现使用兜底方法可以返回更友好的错误信息
配置blockHandler
修改方法:com.antherd.springcloud.alibaba.controller.CircleBreakerController.fallback 的注解
@SentinelResource(value = "fallback", blockHandler = "blockHandler") // blockHandler只负责sentinel控制台配置违规
注释掉handlerFallback方法,并添加方法 handlerFallback:
// 本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
Payment payment = new Payment(id, null);
return new CommonResult(445, "blockHandler-sentinel限流,无此流水:blockException " + blockException.getMessage(), payment);
}
在sentinel中新增降级规则
访问:http://localhost:84/consumer/fallback/4 发现先直接返回错误页面,如果快速访问触发熔断机制,返回sentinel blockHandler方法445错误
同时配置fallback、blockHandler
修改方法:com.antherd.springcloud.alibaba.controller.CircleBreakerController.fallback 的注解
@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler")
在sentinel中,删除降级规则,新增流控规则
取消handlerFallback方法的注释
访问:http://localhost:84/consumer/fallback/1 可以正常访问,快速多次访问会被限流,返回445
访问:http://localhost:84/consumer/fallback/4 返回兜底方法,返回444,快速多次访问会被限流,返回445,由此可见,若blockHandler和fallback都进行了配置并且都达到触发条件,blockHandler优先级高于fallback
exceptionsToIgnore
修改方法:com.antherd.springcloud.alibaba.controller.CircleBreakerController.fallback 的注解
@SentinelResource(value = "fallback", fallback = "handlerFallback",
blockHandler = "blockHandler",
exceptionsToIgnore = { IllegalArgumentException.class })
访问:http://localhost:84/consumer/fallback/4 又直接返回错误页面了,没有被fallback方法处理
Sentinel配置OpenFeign
-
改pom,添加OpenFeign依赖
<!-- SpringCloud OpenFeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
改yml,激活Sentinel对Feign的支持
# 激活Sentinel对Feign的支持 feign: sentinel: enabled: true
-
改主启动类,添加如下注解
@EnableFeignClients
-
新建接口:com.antherd.springcloud.alibaba.service.PaymentService
package com.antherd.springcloud.alibaba.service; import com.antherd.springcloud.entities.CommonResult; import com.antherd.springcloud.entities.Payment; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "nacos-payment-provider", fallback = PaymentFallbackService.class) public interface PaymentService { @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id); }
新建类:com.antherd.springcloud.alibaba.service.PaymentFallbackService
package com.antherd.springcloud.alibaba.service; import com.antherd.springcloud.entities.CommonResult; import com.antherd.springcloud.entities.Payment; import org.springframework.stereotype.Component; @Component public class PaymentFallbackService implements PaymentService { @Override public CommonResult<Payment> paymentSQL(Long id) { return new CommonResult<>(444444, "服务降级返回, *****PaymentFallbackService", new Payment(id, "errorSerial")); } }
-
修改类:com.antherd.springcloud.alibaba.controller.CircleBreakerController,添加新接口
// *****************OpenFeign*************** @Resource private PaymentService paymentService; @GetMapping(value = "/consumer/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) { return paymentService.paymentSQL(id); }
-
package com.alibaba.cloud.sentinel.feign; import feign.Contract; import feign.MethodMetadata; import java.util.HashMap; import java.util.List; import java.util.Map; public class SentinelContractHolder implements Contract { private final Contract delegate; /** * map key is constructed by ClassFullName + configKey. configKey is constructed by {@link * feign.Feign#configKey} */ public final static Map<String, MethodMetadata> METADATA_MAP = new HashMap<>(); public SentinelContractHolder(Contract delegate) { this.delegate = delegate; } @Override public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) { List<MethodMetadata> metadatas = delegate.parseAndValidatateMetadata(targetType); metadatas.forEach(metadata -> METADATA_MAP .put(targetType.getName() + metadata.configKey(), metadata)); return metadatas; } }
-
启动测试
启动:cloudalibaba-provider-payment9003、cloudalibaba-consumer-nacos-order84 两个模块
访问:http://localhost:84/consumer/paymentSQL/1 正常,停止cloudalibaba-provider-payment9003模块,再访问http://localhost:84/consumer/paymentSQL/1 返回服务降级444444
服务熔断框架对比:
项目 | Sentinel | Hystrix | resilience4j |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于RxJava) | Ring BIt Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
拓展性 | 多个拓展点 | 插件形式 | 接口形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
控制台 | 提供开箱即用的控制台,可以配置规则、查看秒级监控、机器发现等 | 简单的监控查看 | 不提供控制台、可对接其他监控系统 |