1.斷路器(Circuit Breaker)模式
? ? ? ??在上文中,我們?nèi)藶橥5袅艘粋€provider,在實際的生產(chǎn)環(huán)境中,因為意外某個服務(wù)down掉,甚至某一層服務(wù)down掉也是會是有發(fā)生的。一旦發(fā)生這種情況,我們需要將損失減少到最低限度。
? ? ? ??那怎么減少損失。在電力系統(tǒng)中,如果某個電器發(fā)生過載等問題,該段電路的繼電器中的保險絲就會熔斷。在分布式系統(tǒng)中,我們也可以設(shè)計這樣的模式,并為它賦有專有名詞:斷路器(Circuit Breaker)模式。
? ? ? ??其基本模式在Martin Fowler的一篇文章中進行過專有描述,其大概的架構(gòu)圖如下:

? ? ? ??它描述了兩個狀態(tài):close、open,以及一個動作:trip,
? ? ? ??close狀態(tài)下, client通過熔斷器向supplier發(fā)起的服務(wù)請求, supplier的返回值經(jīng)過熔斷器返回client。
? ? ? ??open狀態(tài)下,c client通過熔斷器向supplier發(fā)起的服務(wù)請求,熔斷器直接返回值給client, client和supplier之間被隔斷。
? ? ? ??Trip動作: 如果在close狀態(tài)下, supplier持續(xù)超時報錯, 熔斷器就進行trip,然后熔斷器將狀態(tài)從close進入open。
? ? ? ??除了基本模式,Martin Fowler還描述了一種擴展模式。即熔斷器定期探測supplier的服務(wù)的狀態(tài), 一旦服務(wù)恢復(fù), 就將狀態(tài)設(shè)置回close,并且熔斷器進行重試時的狀態(tài)為half-open狀態(tài)。

? ? ? ??對于熔斷器模式,不再詳細展開。接下來我們看看在SpringCloud的系統(tǒng)中,熔斷器是怎么提供的。
2.Hystrix熔斷與服務(wù)降級
? ? ? ??SpringCloud Netflix實現(xiàn)的熔斷器叫Hystrix。我們首先看看微服務(wù)架構(gòu)下, 瀏覽器如何訪問后臺服務(wù),

? ? ? ??然后,服務(wù)異常情況下,Hystrix通過提供Fallback進行了熔斷的保護,

? ? ? ??Hystrix設(shè)定的熔斷閾值是:5秒之內(nèi)發(fā)生20次調(diào)用失敗,然后熔斷器就會被處于open狀態(tài), 在熔斷狀態(tài)下,服務(wù)不再被調(diào)用, Hystrix提供一個Fallback回調(diào)。當然,這個回調(diào)可以由我們實現(xiàn)。
? ? ? ??Fallback是一種降級操作,這種行為我們定義為:服務(wù)降級。
3.實現(xiàn)
? ? ? ??首先,在服務(wù)接口的聲明中,加入FeignClient注解的fallback屬性,
package com.zuikc;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "hello-service",fallback = FeignFallBack.class)
public interface HelloService {
? ? //服務(wù)中方法的映射路徑
? ? @RequestMapping("/hello")
? ? String hello();
}
? ? ? ??注意,假設(shè)這里我們沒有使用FeignClient注解,而是原先那種url方式來啟動LB的話,那么,那么就需要在具體的service中直接使用注解:@HystrixCommand(fallbackMethod = "helloFallBack"),來實現(xiàn)熔斷和服務(wù)降級。helloFallBack可以是具體服務(wù)類中的一個指定的方法。
? ? ? ??接下來,然后接著說FeignClient,實現(xiàn)該FeignFallBack類,
package com.zuikc;
import org.springframework.stereotype.Component;
/**
?* @ClassName FeignFallBack
?* @Description 我們提供咨詢和培訓(xùn)服務(wù),關(guān)于本文有任何困惑,請關(guān)注并聯(lián)系“碼農(nóng)星球”
?* @Author 碼農(nóng)星球
?**/
@Component
public class FeignFallBack implements HelloService {
? ? //實現(xiàn)的方法是服務(wù)調(diào)用的降級方法
? ? @Override
? ? public String hello() {
? ? ? ? return "error";
? ? }
}
? ? ? ??這個類實現(xiàn)了HelloService。如果provider調(diào)用失敗,就會執(zhí)行該類的實現(xiàn)。
? ? ? ??最后,還得配置,
server:
? port: 9291
spring:
? application:
? ? name: Ribbon-Consumer
eureka:
? client:
? ? service-url:
? ? ? defaultZone: http://localhost:9091/eureka/
#providers這個是自己命名的,ribbon,listOfServer這兩個是規(guī)定的
providers:
? ribbon:
? ? listOfServers: http://localhost:9191/eureka,http://localhost:9192/eureka
feign:
? hystrix:
? ? enabled: true
? ? ? ??粗體部分就是新加的配置。Feign默認禁用熔斷器,所以我們需要配置為enabled。
? ? ? ??經(jīng)過以上功能的改進后,停止provider吧,看看結(jié)果是什么呢?

4.監(jiān)控
? ? ? ??SpringCloud做的比dubbo好的一點就是其監(jiān)控非常的明了。我們可以用hystrix的監(jiān)控方便的看到熔斷器的數(shù)據(jù)指標。
? ? ? ??要想監(jiān)控這些數(shù)據(jù),我們還得繼續(xù)改造我們的項目。
? ? ? ??首先,在provider的pom中加入依賴:
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? ? ? <artifactId>spring-boot-actuator</artifactId>
? ? ? ? </dependency>
? ? ? ??其次,在我們ribbon項目中,加入依賴:
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>com.netflix.hystrix</groupId>
? ? ? ? ? ? <artifactId>hystrix-javanica</artifactId>
? ? ? ? ? ? <version>RELEASE</version>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
? ? ? ? </dependency>
? ? ? ??第一個依賴表示我們得有監(jiān)控,第二個依賴表示我們得有一個儀表盤。
? ? ? ??接著,讓我們在ribbon的啟動類中加入一個servlet,如下:
package com.zuikc;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
?* @ClassName ServiceRibbonApplication
?* @Description 我們提供咨詢和培訓(xùn)服務(wù),關(guān)于本文有任何困惑,請關(guān)注并聯(lián)系“碼農(nóng)星球”
?* @Author 碼農(nóng)星球
?**/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class ServiceRibbonApplication {
? ? public static void main(String[] args) {
? ? ? ? SpringApplication.run(ServiceRibbonApplication.class, args);
? ? }
? ? @Bean
? ? @LoadBalanced
? ? RestTemplate restTemplate() {
? ? ? ? return new RestTemplate();
? ? }
?@Bean
? ? public ServletRegistrationBean getServlet(){
? ? ? ? HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
? ? ? ? ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
? ? ? ? registrationBean.setLoadOnStartup(1);
? ? ? ? registrationBean.addUrlMappings("/actuator/hystrix.stream");
? ? ? ? registrationBean.setName("HystrixMetricsStreamServlet");
? ? ? ? return registrationBean;
? ? }
}
? ? ? ??在這個啟動類中,除了這個servlet要注冊之外,就是加入
? ? ? ??@EnableCircuitBreaker
? ? ? ??@EnableHystrixDashboard
? ? ? ??這兩個注解了。注意,由于hystrix默認就是支持熔斷器的,所以@EnableCircuitBreaker注解之前我們并沒有加。但是,這里要使用監(jiān)控了,就必須要加入這個注解了。
? ? ? ??以上都操作完畢。來打開:http://localhost:9291/hystrix。
? ? ? ??然后在出來的如下界面中,首先填入servlet的地址,其次點擊下面的monitor按鈕,

? ? ? ??最終進入到如下這個監(jiān)控儀表盤界面。每一次對provider的調(diào)用,都會清清楚楚被儀表盤呈現(xiàn)出來。

? ? ? ??Ok。本章告一段落。
? ? ? ??感謝關(guān)注“碼農(nóng)星球”。本文版權(quán)屬于“碼農(nóng)星球”。我們提供咨詢和培訓(xùn)服務(wù),關(guān)于本文有任何困惑,請關(guān)注并聯(lián)系我們。
本文的參考1:
https://martinfowler.com/bliki/CircuitBreaker.html
本文的參考2:
http://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html