天天看點

詳細講解springcloud第三章:-------在springcloud中配置并使用hystrix斷容器中的熔斷與降級

5.Hystrix(相當重要,100%的項目都必須有容錯,否則無法部署正式上線環境)

斷容器
	斷容器其實就是類似于保險絲的功能,當某些家用電器短路,保險絲就會被燒斷,保證了整個電路的安全
	斷容器就是在整個微服務項目中,突然有一個服務當機,其他的服務就無法調用這個當機的服務,長時間以後會出現連接配接逾時,服務調用方就會報出500的異常,用戶端會直接顯示該異常,斷容器就可以解決這個問題
           

引起斷容的兩個概念

服務的扇出
			如果有一個服務A
				這個服務A需要分别調用服務B,C,D,當服務A成功的擷取到了BCD的值以後才算服務A成功調用,但是B調用E,C調用F和G,D又調用H,I,J,這種調用模式就稱之為服務的扇出

		服務的雪崩效應
			在這個時候,隻要有一條線上的服務因為某一些原因導緻響應時間過長或者當機,那麼整個A服務就必須處于等待狀态,如果隻有一個請求還可以接受,但是突然之間用戶端來了10萬的并發,10萬的并發走到當機的地方全部擠壓,導緻整個微服務項目一直處于等待狀态,進而會引起系統的資源的緊張,最終導緻項目崩潰,這種就稱之為雪崩效應

		說到斷容器就必須知道服務的容錯:
           

什麼是容錯?

當項目出現異常的情況下,仍然可以正常的運作,這種模式就叫做容錯(try/catch)
           

斷容器的四大核心:(面試必問)

1.限流(解決高并發)
			限制流量
			當伺服器的壓力比較大的時候,也就是負載比較多的時候,就不能再繼續支撐服務,還有100個請求伺服器就會當機,現在規定隻能再接收20個請求,超過20個請求直接走斷容
		2.熔斷(監聽)
			當伺服器調用的時候出現故障,項目就會出現嚴重異常,熔斷就是解決這個嚴重的異常去做補救措施
		3.降級
			當伺服器壓力過大的時候,為了支撐核心業務的正常運作,先把無關緊要的服務停止來拓展核心項目的資源,當核心業務伺服器性能恢複之後,再重新啟動這些其他的項目,這種模式就叫做服務的降級
		4.隔離()
			線程池隔離
			信号量隔離
			當服務長時間不響應,就會連接配接逾時,隔離解決這個問題特别棒!
           

5.1.熔斷的實作

5.1.1.建立provider-hystrix-8084項目

5.1.2.添加jar包

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

5.1.3.測試熔斷

先啟動三台eureka
			再啟動8084和8081
			最後啟動6082(ribbon)
           

5.2.服務降級(包含了熔斷,但是服務降級并不是熔斷)

熔斷有什麼弊端?
		provider中有controller(10個)-->每一個controller中有20個被@RequestMapping所标注的方法,也就是說必須要實作200個後備方法,整個檔案就會非常大,而且耦合度非常高!!
		當耦合度比較高的時候,并且檔案比較大的時候,可以采取封裝的方式把整個備用方法全部提取出來

		consumer調用-->provider的時候,provider直接當機,這個時候consumer就無法請求到provider,也就是說consumer還沒有調用到provider中方法的時候就已經報錯,熔斷就沒有意義了!!

		feign-->controller調用service(接口)
			!也就是說當service接口出現異常的時候,整個consumer就會出現異常!
			直接捕獲service(接口)
				IUserService(I):
					@RequestMapping("/userAll")-->provider的controller中的RequestMapping("/userAll")
					List<User> selectAllUsers();

				監視selectAllUsers()抽象方法-->一旦發現抽象方法抛出異常-->直接調用該抽象方法的備用方法!
           

management-api項目中

建立一個類(IUserServiceFackBallFactory),該類就是IUserService接口的備用類,因為要實作解耦
				通過IUserServiceFackBallFactory如何實作對IUserService的熔斷實作?
				IUserServiceFackBallFactory假設就是IUserService的實作類
				該接口中的所有抽象方法都必須要在IUserServiceFackBallFactory中實作

			需要把IUserServiceFackBallFactory類實作接口(Hystrix所提供)FallbackFactory
			FallbackFactory有一個泛型,泛型傳什麼對象?
				泛型就是傳遞IUserService接口
			因為在接口中所有的方法都必須是抽象方法
			eg:
				IUserService
					-->是需要讓程式員自己實作的
					-->!如果程式員沒有實作這個接口,則程式是會報錯!
					-->為了提升整個項目的容錯率,架構師會預設去提供一個實作
					UserServieImpl implements IUserService
						如果程式員最終沒有實作IUserService,則會走預設的實作,如果一旦程式員實作了IUserService接口後,就會使用程式員所實作該接口的實作類

			eg:
				servlet生命周期:
					1.加載并執行個體化
					2.初始化
						init(),這個方法從來都沒有重寫過
						LoginServlet extends HttpServlet(init())
						--->重寫了init方法,整個項目就不會再用HTTPServlet所提供的init方法
						init()并不會寫,當servlet啟動的時候,需要初始化表中的資料
							必須要重寫init方法,但是目前不會寫,怎麼辦?
						init(),init(param)
						其實真正servlet加載的帶參數的方法,init不帶參數的方法是給程式員使用

						init() {
							System.out.println("初始化servlet");
						}
						init()是什麼時候調用的?
							在init(param)方法加載servlet所必須的配置代碼之後才會調用init()
							init(param){
								// 加載servlet配置代碼
								init();// 報錯!
							}

					3.調用service/doGet和doPost(處理業務,提供服務)
					4.銷毀
           

5.3.!在springcloud2.x中強制要求微服務的細粒度化!

粗粒度
			consumer(商城:訂單,購物車,登入,使用者資訊...) ---> provider(商城)
		細粒度
			consuer1(訂單) ---> provider1(訂單)
			consumer2(購物車) ---> provider2(購物車)
			consumer3(使用者資訊) ---> provider3(使用者資訊)
		!!!!一個consumer和一個provider隻能有一個Fallback類!!!!
			所有的controller隻能共用一個Fallback類
           

fallback類的具體代碼

@Component   
     public class IUserServiceFallbackFactory implements FallbackFactory<IUserService> {
        @Override
         public IUserService create(Throwable throwable) {
          // create傳回的是一個接口
            return new IUserService() {
              @Override
               public List<User> selectAllUsers() {
                     System.out.println("測試服務熔斷,IUserService已經抛出異常!");
            return null;
        }
    };
}
}
           

繼續閱讀