sbc(五)Hystrix-服務容錯與保護

1
1

前言

看過 應用限流的朋友應該知道,限流的根本目的就是爲了保障服務的高可用。java

本次再借助SpringCloud中的集成的Hystrix組件來談談服務容錯。node

其實產生某項需求的緣由都是爲了解決某個需求。當咱們將應用進行分佈式模塊部署以後,各個模塊之間經過遠程調用的方式進行交互(RPC)。拿咱們平時最多見的下單買商品來講,點擊下單按鈕的一瞬間可能會向發送的請求包含:git

  • 請求訂單系統建立訂單。
  • 請求庫存系統扣除庫存。
  • 請求用戶系統更新用戶交易記錄。

這其中的每一步都有可能由於網絡、資源、服務器等緣由形成延遲響應甚至是調用失敗。當後面的請求源源不斷的過來時延遲的資源也沒有的到釋放,這樣的堆積頗有可能把其中一個模塊拖垮,其中的依賴關係又有可能把整個調用鏈中的應用Over最後致使整個系統不可能。這樣就會產生一種現象:雪崩效應github

以前講到的限流也能起到必定的保護做用,但還遠遠不夠。咱們須要從各個方面來保障服務的高可用。spring

好比:express

  • 超時重試。
  • 斷路器模式。
  • 服務降級。
    等各個方面來保障。

使用Hystrix

SpringCloud中已經爲咱們集成了Netflix開源的Hystrix框架,使用該框架能夠很好的幫咱們作到服務容錯。springboot

Hystrix簡介

下面是一張官方的流程圖:bash

簡單介紹下:服務器

在遠程調用時,將請求封裝到HystrixCommand進行同步或是異步調用,在調用過程當中判斷熔斷器是否打開、線程池或是信號量是否飽和、執行過程當中是否拋出異常,若是是的話就會進入回退邏輯。而且整個過程當中都會收集運行狀態來控制斷路器的狀態。網絡

不但如此該框架還擁有自我恢復功能,當斷路器打開後,每次請求都會進入回退邏輯。當咱們的應用恢復正常後也不能再進入回退邏輯吧。

因此hystrix會在斷路器打開後的必定時間將請求發送到服務提供者,若是正常響應就關閉斷路器,反之則繼續打開,這樣就能很靈活的自我修復了。

Feign整合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中管理起來。這樣上文中@FeignClientconfiguration屬性就起到做用了,來看看對應的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:

fallbackFactoryfallback屬性不可共用。

Hystrix監控

Hystrix還自帶了一套監控組件,只要依賴了spring-boot-starter-actuator便可經過/hystrix.stream端點來得到監控信息。

冰冷的數據確定沒有實時的圖表來的直觀,因此Hystrix也自帶Dashboard

Hystrix與Turbine聚合監控

爲此咱們新建了一個應用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只是一個入門版,後面會持續分析它的線程隔離、信號量隔離等原理。

項目:github.com/crossoverJi…

博客:crossoverjie.top

相關文章
相關標籤/搜索