目录
服务雪崩
什么是服务雪崩
服务不可用原因
解决方案
技术选型对比
Sentinel
介绍
优点
核心概念
资源
规则
代码实战
API实现
@SentinelResource注解实现
Sentinel控制台
启动控制台服务
java应用接入控制台
微服务接入Sentinel
服务雪崩
什么是服务雪崩
在服务调用链路中, 服务提供者不可用, 导致服务调用者不可用, 间接让上上游也不可用, 这个不可用逐渐放大的过程, 叫做服务雪崩
服务不可用原因
- 内存泄漏
- 大流量请求, 超过正常承受qps
- 缓存击穿, 大量直接打到数据库
- 硬件损坏
解决方案
1. 超时机制
2. 限流
3. 资源隔离(线程池/信号量隔离)
4. 熔断降级
技术选型对比
Sentinel
介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
官方文档: https://sentinelguard.io/zh-cn/docs/introduction.html
优点
- 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
- 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
核心概念
资源
资源可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。一个资源可以对应多个规则, 一个规则只能对应一个资源.
代码实战
API实现
1. 引入maven依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version>
</dependency>
2. 接口实现
@RestController
@Slf4j
public class HelloController {// 定义资源名称private static final String RESOURCE_NAME = "HelloWorld";@RequestMapping(value = "/hello")public String hello() {// try catch包起来的代码块 就是资源try (Entry entry = SphU.entry(RESOURCE_NAME)) {// 被保护的逻辑log.info("hello world");return "hello world";} catch (BlockException ex) {// 自定义流控逻辑log.info("blocked!");return "被流控了";}}/*** 定义流控规则*/@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置受保护的资源rule.setResource(RESOURCE_NAME);// 设置流控规则 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置受保护的资源阈值, qps>1 就被流控rule.setCount(1);rules.add(rule);// 加载配置好的规则FlowRuleManager.loadRules(rules);}
}
存在缺点: 代码侵入太强, 不够灵活
@SentinelResource注解实现
1. 引入pom依赖, sentinel核心jar和切面jar
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>1.8.6</version></dependency>
2. 注入切面类
@Configuration
public class SentinelAspectConfiguration {@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}
}
3. 设置流控规则注解, 注解定义资源以及降级逻辑
@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置受保护的资源rule.setResource(RESOURCE_NAME);// 设置流控规则 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置受保护的资源阈值rule.setCount(3);rules.add(rule);// 加载配置好的规则FlowRuleManager.loadRules(rules);}@SentinelResource(value = RESOURCE_NAME,blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class,fallback = "fallbackException",fallbackClass = ExceptionUtil.class)@RequestMapping("/hello2")public String hello2() {int i = 1 / 0;return "helloworld ";}
public class ExceptionUtil {public static String fallbackException(Throwable t){return "===被异常降级啦===";}public static String handleException(BlockException ex){return "===被限流啦===";}
}
Sentinel控制台
启动控制台服务
官方文档:https://sentinelguard.io/zh-cn/docs/dashboard.html
1. 下载控制台
https://github.com/alibaba/Sentinel/releases/download/1.8.7/sentinel-dashboard-1.8.7.jar
2. 启动控制台
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar
3. 登录控制台
访问http://localhost:8080/#/login ,默认用户名密码: sentinel/sentinel
java应用接入控制台
1. 引入sentinel通信jar
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.6</version></dependency>
2. java应用增加启动参数, 启动服务
-Dproject.name=kk-sentinel-demo -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.api.port=8719
3. 访问流控接口http://localhost:8800/hello, 登录控制台检查
4. 控制台修改流控规则, 接口测试, 实时生效
5. get接口查看流控规则, url = http://localhost:8720/getRules?type=flow
微服务接入Sentinel
1. 引入pom依赖
<!--sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!-- 对外暴露的 Endpoint --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
2. 修改yml配置
server:port: 8800feign:sentinel:enabled: true #开启Sentinel 对 Feign 的支持spring:application:name: mall-usercloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8080# 指定应用与Sentinel控制台交互的端口,应用会起一个HttpServer占用该端口# port: 8719#暴露actuator端点 http://localhost:8800/actuator/sentinel
management:endpoints:web:exposure:include: '*'
3. 对URL流控
// 对URL流控@RequestMapping("/info/{id}")@SentinelResource(value = "userinfo", blockHandler = "handleException")public R info(@PathVariable("id") Integer id){UserEntity user = userService.getById(id);if(id==4){throw new IllegalArgumentException("异常参数");}return R.ok().put("user", user);}// 对子方法流控@SentinelResource(value = "getUser",blockHandler = "handleException")public UserEntity getById(Integer id) {return userDao.getById(id);}
4. 接入openFeign 熔断降级
@FeignClient(value = "mall-order",path = "/order",fallbackFactory = FallbackOrderFeignServiceFactory.class)
public interface OrderFeignService {@RequestMapping("/findOrderByUserId/{userId}")public R findOrderByUserId(@PathVariable("userId") Integer userId);
}@Component
public class FallbackOrderFeignServiceFactory implements FallbackFactory<OrderFeignService> {@Overridepublic OrderFeignService create(Throwable throwable) {return new OrderFeignService() {@Overridepublic R findOrderByUserId(Integer userId) {return R.error(-1,"=======服务降级了========");}};}
}