日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/10/5 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试官:了解雪崩效应吗?了解Hystrix吗?怎么解决雪崩效应吗?(大型社死现场,教你运筹帷幄之中) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上篇我們模擬了高并發場景下,系統資源被耗盡導致其他接口訪問非常之慢。至此,這篇給出了五種解決方案(當然這個是次要的,主要還是理解原理)
上篇地址: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已經進入維護之中,但是這個組件真的香,我一直都認為學習不能什么熱就學什么,為什么不去探究一下其中的奧妙呢?深入學習之后我發現

溜了溜了!

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的面试官:了解雪崩效应吗?了解Hystrix吗?怎么解决雪崩效应吗?(大型社死现场,教你运筹帷幄之中)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。