上篇我们模拟了高并发场景下,系统资源被耗尽导致其他接口访问非常之慢。至此,这篇给出了五种解决方案(当然这个是次要的,主要还是理解原理)
上篇地址:https://blog.csdn.net/Kevinnsm/article/details/117302197?spm=1001.2014.3001.5501

文章目录

  • 一、雪崩效应是什么?
  • 二、什么是Hystrix?
  • 三、Hystrix用来解决什么问题?
  • 四、雪崩效应的五大解决方案
    • 1、请求缓存
      • Ⅰ、redis安装
      • Ⅱ、代码配置
      • Ⅲ、启动测试接口
      • Ⅳ、模拟2500访问量高并发测试
    • 2、请求合并
    • 3、服务隔离
      • 1、线程隔离
      • 2、信号量隔离
    • 4、服务熔断
    • 5、服务降级
  • 五、总结

一、雪崩效应是什么?

在微服务项目当中,服务之间的调用是错综复杂的,服务之间相互依赖;一旦某个服务发生了问题,那么将可能出现链式反应,导致整个系统崩溃,这就是所谓的雪崩效应
(大白话说就是A服务依赖(调用)B服务,B服务依赖C服务,一旦C服务出了问题,那么A、B服务将一直处于阻塞状态)

二、什么是Hystrix?

Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟、异常,引起资源耗尽导致系统不可用的解决方案。

Hystrix地址:https://github.com/Netflix/Hystrix

三、Hystrix用来解决什么问题?

服务之间错综复杂的调用,如果某一个服务出现了问题,那么就会出现我们前面介绍的雪崩效应问题。而Hystrix为这个服务故障提供了一套解决方案。
例如:

1、请求缓存
2、请求合并
3、服务隔离
4、服务熔断
5、服务降级

当你回答到这,面试官估计会对你嘿嘿一笑,说:来做CTO吧



上篇我们模拟了高并发场景下,系统资源被耗尽导致其他接口访问非常慢。至此,这篇给出了五种解决方案

演示代码免费下载地址:https://download.csdn.net/download/Kevinnsm/19098746



四、雪崩效应的五大解决方案

1、请求缓存

Ⅰ、redis安装

此处为了方便,我直接在windows上进行快速安装

另外我也使用了Reids Desktop Manager(图形化界面),这个现在收费了,不过对于我们来说,肯定白嫖!

Ⅱ、代码配置

在consumer模块配置RedisConfig文件

@Configuration
public class RedisConfig {//    重写RedisTemplate序列@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();
//        为String类型key设置序列化器template.setKeySerializer(new StringRedisSerializer());
//        为String类型value设置序列化器template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//        为Hash类型key设置序列化器template.setHashKeySerializer(new StringRedisSerializer());
//        为Hash类型Value设置序列化器template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.setConnectionFactory(redisConnectionFactory);return template;}
//    重写Cache序列public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
//                设置默认时间为30秒.entryTtl(Duration.ofMinutes(30))
//                设置key和value的序列化.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);}
}

redis配置

在启动类上开启缓存

在远程调用接口上开启缓存配置(第一个接口和第三个接口)
具体不明白的可以参考上一篇

@FeignClient(value = "service-provider")
public interface ProductService {@GetMapping(value = "/product/list")@Cacheable(cacheNames = "orderService:product:list")List<Product> selectProductList();@GetMapping(value = "/product/byIds")List<Product> selectProductListByIds(@RequestBody List<Integer> ids);@GetMapping(value = "/search/{id}")@Cacheable(cacheNames = "orderService:product:single", key = "#id")Product selectProductById(@PathVariable("id") Integer id);
}

Ⅲ、启动测试接口

启动这四个服务访问http://localhost:9090/select/1
由于我们在第一个消费接口的服务提供类的接口处暂停了两秒,所以当我们访问时,第一次会耗时>2s,后面就会非常快了,因为从缓存读取了嘛!

之后我们从RedisManager查看结果

Ⅳ、模拟2500访问量高并发测试

和上一篇操作一样:https://blog.csdn.net/Kevinnsm/article/details/117302197?spm=1001.2014.3001.5501

此时我们可以看到结果

为什么2500个请求很快就完成了呢?究其原因还是缓存的功劳嘛!一般情况下从第二个请求开始就一直从缓存中取的数据。虽然我暂停了两秒,但那和缓存没毛线关系(就第一次走那个路线)。


在那2500个请求的过程中,访问第三个接口,有可能2499个请求都找缓存去了,然后就不存在线程资源竞争嘛!当然就很快了


2、请求合并

什么是请求合并?
在高并发场景下,一个请求就需要一个线程进行处理;一旦访问量很大,那么就会浪费很多的资源;所以引入了请求合并,将多个请求进行拼接,只进行一次访问即可。

hystrix依赖

         <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>2.2.8.RELEASE</version></dependency>


这两个注解配置一下即可

@HystrixCollapser(batchMethod = "searchOrderById",                    //合并请求方法scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,      //请求方式collapserProperties = {//请求的最大等待时间 - 30s ,默认20s@HystrixProperty(name = "timeDelayInMilliseconds", value = "30"),//最多合并多少个请求 - 200个@HystrixProperty(name = "maxRequestsInBatch", value = "200")})

注意启动类上需要开启Hystrix熔断。


3、服务隔离

1、线程隔离

什么是线程隔离?
我们以前没有使用线程隔离的项目的所有接口都运行在一个ThreadPool中,一旦某一个接口压力过大就会造成资源耗尽,从而导致其他接口的正常使用;如使用了线程隔离技术,我们可以将某个实例接口单独使用ThreadPool隔离起来,一旦它出现故障,不会影响其他接口的使用,如下图详解两种方式


异步,提高了系统的并发性;但是如果隔离的实例过多,还是推荐使用这种方式

使用注解方式实现线程隔离,注解方式和配置方式各有优缺点

配置方式可以在服务在线时进行修改配置,但是一个实例需要一个配置类,一旦需要隔离较多的实例就要写很多类
注解方式虽然很方便,但是不能在服务在线时进行修改配置

@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate ProductService productService;@Override@HystrixCommand(groupKey = "consumer-product-pool-1",       //服务名称commandKey = "selectOrderById",                     //接口名称,默认方法名threadPoolKey = "consumer-product-pool-1",             //线程池名称,相同名称使用一个线程此commandProperties = {//超时时间。默认1000ms@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")},threadPoolProperties = {//线程大小@HystrixProperty(name = "coreSize", value = "6"),//队列等待阈值@HystrixProperty(name = "maxQueueSize", value = "100"),//线程存活时间@HystrixProperty(name = "keepAliveTimeMinutes", value = "30"),//超出队列等待阈值执行拒绝策略@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")})public Order selectOrderById(Integer id) {return new Order(id, "one", "china", 199D,productService.selectProductList());}private List<Product> selectProductListFallback() {return Arrays.asList(new Product(1, "默认数据1", 9, 100D),new Product(2, "默认数据2", 15, 200D),new Product(3, "默认数据3", 13, 300D));}@Overridepublic Order queryOrderById(Integer id) {return new Order(id, "two", "nyist", 11D, productService.selectProductListByIds(Arrays.asList(1, 2)));}@Override@HystrixCommand(groupKey = "consumer-product-pool-2",       //服务名称commandKey = "searchOrderById",                     //接口名称,默认方法名threadPoolKey = "consumer-product-pool-1",             //线程池名称,相同名称使用一个线程此commandProperties = {//超时时间。默认1000ms@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")},threadPoolProperties = {//线程大小@HystrixProperty(name = "coreSize", value = "3"),//队列等待阈值@HystrixProperty(name = "maxQueueSize", value = "100"),//线程存活时间@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),//超出队列等待阈值执行拒绝策略@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")})public Order searchOrderById(Integer id) {return new Order(id, "three", "china", 110D, Arrays.asList(productService.selectProductById(3)));}
}

在tomcat进行配置系统最多只能使用10个线程,方便查看结果

使用JMeter进行测试



由于我在注解中配置了该接口每次只能使用6个线程进行处理,可以发现每次会打印6个日志。(我暂停两秒的那个接口)

2、信号量隔离

什么是信号量隔离?
信号量有一个大小,一旦请求的线程数超过了这个信号量的大小,直接获取失败做fallback处理。获取到信号量的线程继续访问,访问完成后归还信号量;当然可以通过上调信号量的大小,来提高系统的性能

同步调用,信号量是不能用于网络环境的;多用于本地环境。

    @HystrixCommand(commandProperties = {//            超时时间@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000"),//信号量隔离@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),//信号量最大并发@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "10")})public Order selectOrderById(Integer id) {return new Order(id, "one", "china", 199D,productService.selectProductList());}

4、服务熔断

为什么要进行服务熔断?
在微服务架构中,可能由于某种原因导致服务出现了过载现象,有可能引发整个系统发生故障;为防止这种情况发生引入服务熔断技术;可以将熔断理解为我们生活中的闸刀。

Hystrix熔断技术原理:

服务模块业务类代码

为了模拟服务熔断,我手动加入异常,使其开启熔断。
访问id=1,下面会报运行时异常,然后就会走fallback函数。

    @HystrixCommand(commandProperties = {//10s内请求大于10个就启动熔断器,默认20个@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10"),//请求错误率大于50%就启动熔断器@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),//熔断5s进行重试请求, 默认5s@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000")},fallbackMethod = "selectProductListFallback")public Order queryOrderById(Integer id) {if (id ==1 )throw new RuntimeException("id=1的信息异常,开始进行服务熔断处理!");return new Order(id, "two", "nyist", 11D, productService.selectProductListByIds(Arrays.asList(1, 2)));}

服务熔断异常执行函数fallback

private Order selectProductListFallback(Integer id) {System.out.println("------------》调用了默认数据000《---------------");return new Order(1, "系统故障,默认数据", "开启熔断", 11D, Arrays.asList(new Product(1,"vim", 2, 11D)));}



可以发现确实是走的fallback函数,服务熔断模拟成功!


5、服务降级

如何理解服务降级?
服务降级是为了保留核心业务,舍弃边缘业务。

 @HystrixCommand(fallbackMethod = "selectProductListFallback")

进行服务降级只需添加这一行代码即可,前面服务熔断已经使用过。

有几种触发条件
1、发生异常
2、调用超时
3、超出服务隔离设置的上限
4、开启服务熔断

五、总结

到这里基本就结束了,这里讲述的都是基于Hystrix的雪崩解决方案,当然其他技术也能实现,比如Feign实现熔断降级等等。虽然Hystrix已经进入维护之中,但是这个组件真的香,我一直都认为学习不能什么热就学什么,为什么不去探究一下其中的奥妙呢?深入学习之后我发现

溜了溜了!

面试官:了解雪崩效应吗?了解Hystrix吗?怎么解决雪崩效应吗?(大型社死现场,教你运筹帷幄之中)相关推荐

  1. 大型社死现场,两程序员互为彼此面试官

    本文转载自程序员八卦 世界之大无奇不有,有些巧合简直就是天作之合,就像下面这位百度程序员和阿里程序员的故事. 某百度程序员发帖吐槽:中午面试了一个阿里程序员,问了他一些刁钻的问题,结果自己晚上去阿里面 ...

  2. 《如何与面试官处朋友》系列-缓存击穿、穿透、雪崩场景原理大调解

    前面我们提到分布式多级缓存架构的全貌,但总感觉少了些什么东西.在这样大的场景下面,如果遇到缓存使用问题那可咋办?但自古英雄出少年,相信此刻你已踏马西去,正走在寻找答案上得夕阳西下.每每面谈Redis大 ...

  3. 面试官:线上环境 FGC 频繁,如何解决?

    前言 这个问题应该是 Java 面试中很经常被问到的一个题目,很多人害怕这个题目. 因为大部分人可能在工作中根本遇不到 FGC 频繁的问题,即使从网上背了点答案,心里也不踏实,因为毕竟不是自己亲自接触 ...

  4. 面试官:哪些场景会产生OOM?怎么解决?

    这个面试题是一个朋友在面试的时候碰到的,什么时候会抛出OutOfMemery异常呢?初看好像挺简单的,其实深究起来考察的是对整个JVM的了解,而且这个问题从网上可以翻到一些乱七八糟的答案,其实在总结下 ...

  5. mysql幻读和不可重复读的区别_面试官:MySQL的可重复读级别能解决幻读吗

    Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 作者:宁愿. 来源:https://juejin.im/post/5c9040e95188252d92095a9e 引言 之前 ...

  6. 不可重复读和幻读的区别_面试官:MySQL的可重复读级别能解决幻读吗

    Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 作者:宁愿. 来源:https://juejin.im/post/5c9040e95188252d92095a9e 引言 之前 ...

  7. 面试官:首屏加载速度慢怎么解决?

    文章目录 前言 首屏加载时间的计算 首屏的定义 首屏加载过程 计算首屏时间 加载慢的原因 面试中常涉及的解决方案 减小入口文件体积 懒加载 减小文件大小 静态资源本地缓存 UI框架按需加载 组件重复打 ...

  8. 某百度程序员中午面试一个阿里程序员,晚上去阿里面试,面试官竟是中午那个人!

    世界之大无奇不有,有些巧合简直就是天作之合,就像下面这位百度程序员和阿里程序员的故事. 某百度程序员发帖吐槽:中午面试了一个阿里程序员,问了他一些刁钻的问题,结果自己晚上去阿里面试,面试官竟然就是中午 ...

  9. 某百度程序员中午面试一个阿里程序员,晚上去阿里面试,面试官竟是中午那个人!...

    世界之大无奇不有,有些巧合简直就是天作之合,就像下面这位百度程序员和阿里程序员的故事. 某百度程序员发帖吐槽:中午面试了一个阿里程序员,问了他一些刁钻的问题,结果自己晚上去阿里面试,面试官竟然就是中午 ...

最新文章

  1. 用命令行方式获取打包签名文件的SHA1和MD5
  2. 如何配置IIS服务器使用的中间证书( 微软 KB954755)
  3. Xamarin Evolve 2016 Keynote回顾
  4. php mysql 连接不上_php连接不上MySQL问题解决办法_PHP教程
  5. bat代码雨代码流星_bat-入门系列-03-判断结构2
  6. 机器学习算法中文视频教程
  7. 深入理解Java反射+动态代理,java开发面试笔试题
  8. 美国智能机市场Android份额逼近苹果iOS
  9. lightGBM用于排序(Learning to Rank )
  10. Windows10重新安装软件商店
  11. java导出excel加水印且加密(已实现)
  12. Unbuntu的安装
  13. 百度啊,你是新年第一惨
  14. MT7628 OpenWRT21 SIM8202驱动ppp拨号rndis拨号
  15. 电商干货!手淘宝贝关键词排名查询
  16. 介绍一些比较方便好用的爬虫工具和服务
  17. PCB拼板邮票孔制作规范!
  18. 进程调度算法FCFS和RR
  19. 怎么在win7中增加“显示桌面”快速启动栏
  20. MS CRM2011库文件升级到CRM2015

热门文章

  1. HAL驱动库学习-ADC
  2. wordpress相关插件及应用模板
  3. C# 十六进制字符串与数值类型之间转换
  4. 使用read_html爬取网页表哥,Python笔记:用read_html()爬取table形式表格的网络数据...
  5. 前端vue适配不同的分辨率_浅析 React / Vue 跨端渲染原理与实现
  6. centos7 php 404,CentOS7 Apache环境配置自定义404错误页面怎么解决
  7. mysql异地备份_MySQL数据库异地备份与还原方法
  8. java 头尾 队列_探索JAVA并发 - 并发容器全家福
  9. java 热补丁_Android热补丁之AndFix原理解析
  10. unity mysql生成cexcel_【C#附源码】数据库文档生成工具支持(Excel+Html)