應對微服務呼叫時的雪崩效應

qq_43346055發表於2020-12-13

簡介

本文是看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"
	)

相關文章