简介
本文是看b站视频的笔记,需要项目代码的话,可以此链接视频(https://www.bilibili.com/video/BV15K4y1h7Di?p=1)中边观看边搭建。
相关文章
https://zhuanlan.zhihu.com/p/69879180
什么是雪崩效应
微服务间彼此调用时,个别微服务阻塞,导致整个调用链阻塞,进而导致大量类似的请求资源阻塞,使得服务不可用。
应对方法
使用redis作为缓存
.pom依赖,spring-boot-starter-data-redis、commons-pool2依赖
.yml文件,配置spring.redis
自定义配置Redis,(写一个配置类)(重写redisTemplate序列化、cache序列化...)
添加注解
在启动类上注解@EnableCaching
在consumer调用方的调用serviceImpl类的方法上,打注解@Cacheable(cacheNames="orderService:product:single", key="#id")
请求合并
(一个比喻:安排一组人过安检,让 十个人/60s内的人 按照 一波/一批 的量来处理,按批过安检)
.pom添加依赖,spring-cloud-starter-netflix-hystrix依赖
添加注解
在启动类上注解@EnableCircuitBreaker(官网使用) 或者 @EnableHystrix
在consumer调用方的调用serviceImpl类的方法上,(比如要合并byId方法,批量成byIds方法),
在byId方法上加注解:
@HystrixCollapser(
batchMethod="byIds",//合并请求方法
scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,//请求方式
collapserProperties = {
//间隔多久的请求会进行合并,默认10ms
@HystrixProperty(name="timerDelayInMilliseconds", value="20")
//批处理之前,批处理中允许的最大请求数
@HystrixProperty(name="maxRequestsInBatch", value="200")
}
)
在byIds方法上加注解:
@HystrixCommand
服务隔离
线程池隔离
多个接口,在一个线程池中 --> 把接口放在不同的线程池中
请求线程和调用Provider线程不是同一条线程
线程池隔离实现
添加注解,在ProductServiceImpl.java[远程调用者实现类]的方法上
@HystrixCommand(
groupKey = "order-productService-listPool", //服务名称
threadPoolKey = "order-productService-listPool",//线程池名称
commandKey = "selectProductList",//接口名称,默认为(注解下的)方法名
threadPoolProperties = {
//线程池大小
@HystrixProperty(name="coreSize", value="6")
//队列等待阈值(最大队列长度,默认-1)
@HystrixProperty(name="maxQueueSize", value="100")
//线程存活时间,默认 1min
@HystrixProperty(name="keepAliveTimeMinutes", value="2")
//超出队列等待阈值执行拒绝策略
@HystrixProperty(name="queueSizeRejectionThreshold", value="100")
}
commandProperties = {
//熔断多少秒后请求重试,默认5s
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value="5000"),
},
//服务降级方法
fallbackMethod = "selectProductByIdFallback"
)
信号量隔离
信号量总数有上限0,一个请求拿到信号量才能继续访问,请求完成归还信号量;没有信号量,则信号量获取失败,直接fallback;
不支持超时,没有办法异步。
请求线程和调用Provider线程是同一条线程
信号量隔离实现
添加注解,在ProductServiceImpl.java[远程调用者实现类]的方法上
@HystrixCommand(
commandProperties = {
//超时时间(远程调用者对被调用者的同步等待时间,超过这个时间就不等了),默认1000ms。
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="5000"),
//信号量隔离,该策略默认值是THREAD,所以要手动配置
@HystrixProperty(name="HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY", value="SEMAPHORE"),
//信号量最大并发,调小一些方便模拟高并发
@HystrixProperty(name="HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS", value="6"),
},
//服务降级方法
fallbackMethod = "selectProductByIdFallback"
)
简单对比
是否支持超时 是否支持熔断 隔离原理 是否是异步调用 资源消耗
线程池隔离 支持 支持 每个服务单独用线程池 支持同步或异步 大
信号量隔离 不支持 支持 通过信号量的计数器 同步调用,不支持异步 小
服务熔断
参考图 (熔断,是一种牺牲局部保证全体的思想)
//熔断开启状态:直接快速失败,五秒后尝试进入熔断关闭
//熔断关闭状态:获得前十秒的失败率,达到一定程度,进入熔断开启
.pom依赖
<!-- spring-cloud netflix hystrix 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
托底方法
private Product selectProductByIdFallback(Integer id){retrun new Product();}
添加注解
在byId方法上加注解:
@HystrixCommand(
commandProperties = {
//10s内请求数大于10个就启动熔断器,当请求符合熔断条件触发fallbackMethod,默认20个
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value="10"),
//(10s内)请求错误率大于50%就启动熔断器
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value="50"),
//熔断多少秒后请求重试,默认5s
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value="5000"),
},
//服务降级方法
fallbackMethod = "selectProductByIdFallback"
)
//添加异常,视频p13 5.10
服务熔断[openfeign版本]
.pom文件,
<!-- 如果使用openfeign,则默认集成了 hystrix 依赖,无需在此添加 -->
.yml文件,开启feign对hystrix支持(如果使用feign)
feign.hystrix.enabled = true
写一个"服务熔断处理处理类" -- fallback.ProductServiceFallback.java
//视频p15 5.00 ,实现接口ProductService<T>,T在这里就是ProductService
添加@Component注解
写一个"捕获异常类", -- fallback.ProductServiceFallbackFactory.java
//视频p16 0.23,实现接口FallbackFactory<T>
添加@Component注解
/** 用ProductServiceFallback替换上面的ProductServiceFallbackFactory */
添加注解
@FeignClient(value="xxx", fallback=ProductServiceFallback.class) 或者
@FeignClient(value="xxx", fallbackFactory=ProductServiceFallbackFactory.class)
服务降级
触发条件
方法抛出 非HystrixBadRequestException异常 时;
方法调用超时;
熔断器开启拦截;
线程池/队列/信号量跑满了;
使用(已包含于"服务熔断"),
@HystrixCommand(
//服务降级方法
fallbackMethod = "selectProductByIdFallback"
方法抛出 非HystrixBadRequestException异常 时;
方法调用超时;
熔断器开启拦截;
线程池/队列/信号量跑满了;
使用(已包含于"服务熔断"),
@HystrixCommand(
//服务降级方法
fallbackMethod = "selectProductByIdFallback"
)