一:雪崩效應
以下圖所示:A做爲服務提供者,B爲A的服務消費者,C和D是B的服務消費者。A不可用引發了B的不可用,並將不可用像滾雪球同樣放大到C和D時,致使整個系統癱瘓,雪崩效應就造成了。java
雪崩過程:web
1:因爲網路或其餘緣由(硬件故障、程序Bug、用戶大量請求)A服務變得不可用,A服務的不可用致使B服務會出現線程的長阻塞,此時若是有大量的請求涌入(用戶重試加大流量),B服務servlet容器線程資源會被消耗完畢。大量請求的積壓,直接致使B服務變慢,最終癱瘓spring
2:B服務癱瘓的癱瘓同理會致使C、D服務的癱瘓,最後致使系統癱瘓編程
二:防雪崩利器
怎麼防止雪崩效應的發生呢? tomcat
解決問題方案:對依賴作隔離,Hystrix就是處理依賴隔離的框架,同時也是能夠幫咱們作依賴服務的治理和監控服務器
依賴隔離分爲兩種,第一種線程池隔離(Thread-pool Rejection),第二種信號量隔離(semaphre Rejection)併發
a):線程隔離
首先:容器線程(tomcat、jetty)與 遠程服務調用線程隔離,即異步執行服務間遠程調用 app
其次:若是依賴多個微服務,多個依賴間相互隔離框架
線上建議線程池不要設置過大,不然大量堵塞線程有可能會拖慢服務器。異步
線程隔離的優勢:
能夠徹底模擬異步調用,方便異步編程。
線程隔離的缺點:
線程開銷
線程隔離的適用場景
不受信服務(第三方接口服務)
有限依賴(依賴的服務不能太多)
NOTE:
Netflix公司內部認爲線程隔離開銷足夠小,不會形成重大的成本或性能的影響。Netflix 內部API 天天100億的HystrixCommand依賴請求使用線程隔,每一個應用大約40多個線程池,每一個線程池大約5-20個線程。
b):信號隔離
信號隔離也能夠用於限制併發訪問,防止阻塞擴散, 與線程隔離最大不一樣在於執行依賴代碼的線程依然是請求線程(該線程須要經過信號申請),
若是客戶端是可信的且能夠快速返回,可使用信號隔離替換線程隔離,下降開銷.
信號隔離優勢
輕量,無額外開銷
信號隔離缺點
不支持異步調用
信號隔離的適用場景
受信服務(公司內部服務)
高依賴(網關)
三:HYSTRIX
a)hystrix簡介
所謂的熔斷機制和平常生活中見到電路保險絲是很是類似的,當出現了問題以後,保險絲會自動燒斷,以保護咱們的電器,程序中咱們也能夠借用這個思想,使用Hystrix實現程序的熔斷。
hystrix對應的中文名字是「豪豬」,豪豬周身長滿了刺,能保護本身不受天敵的傷害,表明了一種防護機制,這與hystrix自己的功能不謀而合,所以Netflix團隊將該框架命名爲Hystrix,並使用了對應的卡通形象作做爲logo。
b)Hystrix快速體驗
Hystrix熔斷限流主要埋在客戶端,因此只須要在服務消費者方集成Hystrix。集成了Hystrix的客戶端,咱們通常稱爲Hystrix客戶端
1:pom依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId> spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
2:啓動類加@EnableCircuitBreaker
3:fallback邏輯
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.wendao.provider.consumer.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "fallback") @RequestMapping("/findOne") public User findOne(){ User user = restTemplate.getForObject("http://SPRING-CLOUD-SERVICE-PROVIDER/user/1", User.class); return user; } //fallback邏輯 private User fallback(){ //TODO .... return new User("fallback",12); } }
4:測試
關閉服務提供者,測試結果以下:
說明:
1:請求服務提供者失敗,怎麼樣算失敗呢?
答:請求超時(默認1秒)算請求失敗,不必定是服務提供者沒啓動,即便服務提供者啓動,可是響應慢,超過了超時時間,同樣請求失敗。
能夠經過下面方式設置超時時間
@HystrixCommand(fallbackMethod = "fallback",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
})
|
2:服務提供者請求失敗,會調用fallback邏輯,當即給客戶端響應,這種狀況叫服務降級
@RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "fallback",commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled",value="true"), @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value="10"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value="10000"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value="50"), }) @RequestMapping("/findOne") public User findOne(){ //若是熔斷器開啓是不會進入這個方法的,直接調用fallback邏輯 System.out.println("come in"); User user = restTemplate.getForObject("http://SPRING-CLOUD-SERVICE-PROVIDER/user/1", User.class); return user; } //fallback邏輯 private User fallback(){ //TODO .... return new User("fallback",12); } }
剛開始你會發現打印come in ,說明主邏輯方法仍是執行了,仍是發送了請求,只不過請求失敗,執行了fallback邏輯,這個時候只是服務降級。
一旦調用失敗次數過大就會致使熔斷器開啓,熔斷器若是open,那麼就不可能讓你繼續執行主邏輯方法了,這時候fallback就成了主邏輯方法
其實上面演示的不是熔斷,熔斷器根本沒開啓,上面演示的只是服務降級。真正的熔斷器開啓是要知足必定條件【閾值】,纔會開啓熔斷器。
快照時間窗:斷路器肯定是否打開須要統計一些請求和錯誤數據,而統計的時間範圍就是快照時間窗,默認爲最近的10秒。
請求總數下限:在快照時間窗內,必須知足請求總數下限纔有資格根據熔斷。默認爲20,意味着在10秒內,若是該hystrix命令的調用此時不足20次,即時全部的請求都超時或其餘緣由失敗,斷路器都不會打開。
circuitBreaker.requestVolumeThreshold
|
錯誤百分比下限:當請求總數在快照時間窗內超過了下限,好比發生了30次調用,若是在這30次調用中,有16次發生了超時異常,也就是超過50%的錯誤百分比,在默認設定50%下限狀況下,這時候就會將斷路器打開。
circuitBreaker.errorThresholdPercentage
|
當熔斷器在10秒內發現請求總數超過20,而且錯誤百分比超過50%,這個時候熔斷器打開。打開以後,再有請求調用的時候,將不會調用主邏輯,而是直接調用降級邏輯,經過斷路器,實現了自動地發現錯誤並將降級邏輯切換爲主邏輯,減小響應延遲的效果。
在斷路器打開以後,處理邏輯並無結束,咱們的降級邏輯已經被成了主邏輯,那麼原來的主邏輯要如何恢復呢?對於這一問題,hystrix也爲咱們實現了自動恢復功能。當斷路器打開,對主邏輯進行熔斷以後,hystrix會啓動一個休眠時間窗,在這個時間窗內,降級邏輯是臨時的成爲主邏輯,當休眠時間窗到期,斷路器將進入半開狀態,釋放一次請求到原來的主邏輯上,若是這次請求正常返回,那麼斷路器將繼續閉合,主邏輯恢復,若是此次請求依然有問題,斷路器繼續進入打開狀態,休眠時間窗從新計時。
六 feign對hystrix的支持
feign只能服務降級,沒法進行服務熔斷,這個是我我的瞭解道德
使用方法:
在aplication。properties文件中添加配置:
feign.hystrix.enabled=true
建立熔斷類這個類是實現調用服務的那個接口的實現類:
@Component//不能忘記加上該註解 public class UserBizImpl implements IUserbiz { @Override public Map update(User user) { return new HashMap(); } }
再修改feign客戶端:
@FeignClient(value="spring-cloud-service-provider",fallback = UserBizImpl.class)
這樣就能夠了