看過 應用限流的朋友應該知道,限流的根本目的就是爲了保障服務的高可用。java
本次再借助SpringCloud
中的集成的Hystrix
組件來談談服務容錯。node
其實產生某項需求的緣由都是爲了解決某個需求。當咱們將應用進行分佈式模塊部署以後,各個模塊之間經過遠程調用的方式進行交互(RPC
)。拿咱們平時最多見的下單買商品來講,點擊下單按鈕的一瞬間可能會向發送的請求包含:git
這其中的每一步都有可能由於網絡、資源、服務器等緣由形成延遲響應甚至是調用失敗。當後面的請求源源不斷的過來時延遲的資源也沒有的到釋放,這樣的堆積頗有可能把其中一個模塊拖垮,其中的依賴關係又有可能把整個調用鏈中的應用Over最後致使整個系統不可能。這樣就會產生一種現象:雪崩效應
。github
以前講到的限流也能起到必定的保護做用,但還遠遠不夠。咱們須要從各個方面來保障服務的高可用。spring
好比:express
SpringCloud
中已經爲咱們集成了Netflix
開源的Hystrix
框架,使用該框架能夠很好的幫咱們作到服務容錯。springboot
下面是一張官方的流程圖:bash
簡單介紹下:服務器
在遠程調用時,將請求封裝到HystrixCommand進行同步或是異步調用,在調用過程當中判斷熔斷器是否打開、線程池或是信號量是否飽和、執行過程當中是否拋出異常,若是是的話就會進入回退邏輯。而且整個過程當中都會收集運行狀態來控制斷路器的狀態。網絡
不但如此該框架還擁有自我恢復功能,當斷路器打開後,每次請求都會進入回退邏輯。當咱們的應用恢復正常後也不能再進入回退邏輯吧。
因此hystrix
會在斷路器打開後的必定時間將請求發送到服務提供者,若是正常響應就關閉斷路器,反之則繼續打開,這樣就能很靈活的自我修復了。
在以前的章節中已經使用Feign
來進行聲明式調用了,而且在實際開發中也是如此,因此此次咱們就直接用Feign來整合Hystrix。
使用了項目原有的sbc-user,sbc-order
來進行演示,調用關係以下圖:
User應用
經過Order
提供出來的order-client
依賴調用了Order
中的建立訂單服務。
其中主要修改的就是order-client
,在以前的OrderServiceClient
接口中增長了如下註解:
@RequestMapping(value="/orderService")
@FeignClient(name="sbc-order",
// fallbackFactory = OrderServiceFallbackFactory.class,
// FIXME: 2017/9/4 若是配置了fallback 那麼fallbackFactory將會無效
fallback = OrderServiceFallBack.class,
configuration = OrderConfig.class)
@RibbonClient
public interface OrderServiceClient extends OrderService{
@ApiOperation("獲取訂單號")
@RequestMapping(value = "/getOrderNo", method = RequestMethod.POST)
BaseResponse<OrderNoResVO> getOrderNo(@RequestBody OrderNoReqVO orderNoReq) ;
}複製代碼
因爲Feign已經默認整合了Hystrix
因此不須要再額外加入依賴。
對應的@FeignClient中的fallback屬性
則是服務容錯中很關鍵的服務降級的具體實現,來看看OrderServiceFallBack
類:
public class OrderServiceFallBack implements OrderServiceClient {
@Override
public BaseResponse<OrderNoResVO> getOrderNo(@RequestBody OrderNoReqVO orderNoReq) {
BaseResponse<OrderNoResVO> baseResponse = new BaseResponse<>() ;
OrderNoResVO vo = new OrderNoResVO() ;
vo.setOrderId(123456L);
baseResponse.setDataBody(vo);
baseResponse.setMessage(StatusEnum.FALLBACK.getMessage());
baseResponse.setCode(StatusEnum.FALLBACK.getCode());
return baseResponse;
}
}複製代碼
該類實現了OrderServiceClient
接口,能夠很明顯的看出其中的getOrderNo()
方法就是服務降級時所觸發的邏輯。
光有實現還不夠,咱們須要將改類加入到Spring
中管理起來。這樣上文中@FeignClient
的configuration
屬性就起到做用了,來看看對應的OrderConfig
的代碼:
@Configuration
public class OrderConfig {
@Bean
public OrderServiceFallBack fallBack(){
return new OrderServiceFallBack();
}
@Bean
public OrderServiceFallbackFactory factory(){
return new OrderServiceFallbackFactory();
}
}複製代碼
其中new OrderServiceFallBack()
並用了@Bean
註解,等同於:
<bean id="orderServiceFallBack" class="com.crossoverJie.order.feign.config.OrderServiceFallBack">
</bean>複製代碼
這樣每當請求失敗就會執行回退邏輯,以下圖:
值得注意的是即使是執行了回退邏輯斷路器也不必定打開了,咱們能夠經過應用的health
端點來查看Hystrix
的狀態。
ps:想要查看該端點須要加入如下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>複製代碼
就拿剛纔的例子來講,先關閉Order
應用,在Swagger
訪問下面這個接口,確定是會進入回退邏輯:
@RestController
@Api("用戶服務API")
@RequestMapping(value = "/userService")
@Validated
public interface UserService {
@ApiOperation("hystrix容錯調用")
@RequestMapping(value = "/getUserByHystrix", method = RequestMethod.POST)
BaseResponse<OrderNoResVO> getUserByHystrix(@RequestBody UserReqVO userReqVO) ;
}複製代碼
查看health
端點:
Hystrix
的狀態依然是UP狀態,代表當前斷路器並無打開。
反覆調用屢次接口以後再次查看health
端點:
發現這個時候斷路器已經打開了。
這是由於斷路器只有在達到了必定的失敗閾值以後纔會打開。
進入回退邏輯以後還不算完,大部分場景咱們都須要記錄爲何回退,也就是具體的異常。這些信息對咱們後續的系統監控,應用調優也有很大幫助。
實現起來也很簡單:
上文中在@FeignClient
註解中加入的fallbackFactory = OrderServiceFallbackFactory.class
屬性則是用於處理回退邏輯以及包含異常信息:
/** * Function:查看fallback緣由 * * @author crossoverJie * Date: 2017/9/4 00:45 * @since JDK 1.8 */
public class OrderServiceFallbackFactory implements FallbackFactory<OrderServiceClient>{
private final static Logger LOGGER = LoggerFactory.getLogger(OrderServiceFallbackFactory.class);
@Override
public OrderServiceClient create(Throwable throwable) {
return new OrderServiceClient() {
@Override
public BaseResponse<OrderNoResVO> getOrderNo(@RequestBody OrderNoReqVO orderNoReq) {
LOGGER.error("fallback:" + throwable);
BaseResponse<OrderNoResVO> baseResponse = new BaseResponse<>() ;
OrderNoResVO vo = new OrderNoResVO() ;
vo.setOrderId(123456L);
baseResponse.setDataBody(vo);
baseResponse.setMessage(StatusEnum.FALLBACK.getMessage());
baseResponse.setCode(StatusEnum.FALLBACK.getCode());
return baseResponse;
}
};
}
}複製代碼
代碼很簡單,實現了FallbackFactory
接口中的create()
方法,該方法的入參就是異常信息,能夠按照咱們的須要自行處理,後面則是和以前同樣的回退處理。
2017-09-21 13:22:30.307 ERROR 27838 --- [rix-sbc-order-1] c.c.o.f.f.OrderServiceFallbackFactory : fallback:java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: sbc-order
。
Note:
fallbackFactory
和fallback
屬性不可共用。
Hystrix還自帶了一套監控組件,只要依賴了spring-boot-starter-actuator
便可經過/hystrix.stream
端點來得到監控信息。
冰冷的數據確定沒有實時的圖表來的直觀,因此Hystrix
也自帶Dashboard
。
爲此咱們新建了一個應用sbc-hystrix-turbine
來顯示hystrix-dashboard
。
目錄結構和普通的springboot
應用沒有差別,看看主類:
//開啓EnableTurbine
@EnableTurbine
@SpringBootApplication
@EnableHystrixDashboard
public class SbcHystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(SbcHystrixTurbineApplication.class, args);
}
}複製代碼
@EnableHystrixDashboard
開啓Dashboard
@EnableTurbine
開啓Turbine
支持。以上這些註解須要如下這些依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>複製代碼
實際項目中,咱們的應用都是多節點部署以達到高可用的目的,單個監控顯然不現實,因此須要使用Turbine來進行聚合監控。
關鍵的application.properties
配置文件:
# 項目配置
spring.application.name=sbc-hystrix-trubine
server.context-path=/
server.port=8282
# eureka地址
eureka.client.serviceUrl.defaultZone=http://node1:8888/eureka/
eureka.instance.prefer-ip-address=true
# 須要加入的實例
turbine.appConfig=sbc-user,sbc-order
turbine.cluster-name-expression="default"複製代碼
其中turbine.appConfig
配置咱們須要監控的應用,這樣當多節點部署的時候就很是方便了(同一個應用的多個節點spring.application.name值是相同的
)。
將該應用啓動訪問http://ip:port/hystrix.stream
:
因爲咱們的turbine和Dashboard是一個應用因此輸入http://localhost:8282/turbine.stream
便可。
詳細指標如官方描述:
經過該面板咱們就能夠及時的瞭解到應用當前的各個狀態,若是再加上一些報警措施就能幫咱們及時的響應生產問題。
服務容錯的整個仍是比較大的,博主也是摸着石頭過河,關於本次的Hystrix
只是一個入門版,後面會持續分析它的線程隔離、信號量隔離等原理。
博客:crossoverjie.top。