1. 程式人生 > >SpringCloud之熔斷器使用(Hystrix)

SpringCloud之熔斷器使用(Hystrix)

前言

熔斷器(Hystrix)的作用就是為了保護被呼叫方、自身不會因為某一個服務請求超時或者某個服務不可用而導致整個請求鏈路掛掉,防止雪崩效應導致這個系統不可用。同時在熔斷器的實現中可以很好的實現服務監控,利於運營維護人員進行及時問題排除。這一篇文章我們主要講如何去使用熔斷器,更多的詳細文件可以進入github熔斷器專案中檢視,hystrix開源專案

使用記錄

1.pom新增hystrix依賴

        <!--hystrix熔斷依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

[email protected](fallbackMethod = "saveOrderFail")進行註解實現熔斷

package com.ckmike.order_service.controller;

import com.ckmike.order_service.service.OrderService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * OrderController 簡要描述
 * <p> TODO:描述該類職責 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-11-7 下午11:49
 * @copyright ckmike
 **/
@RestController
@RequestMapping("/api/v1/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("saveforribbon")
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object saveforRibbon(@RequestParam("user_id") int userId,@RequestParam("product_id") int productId){
        return  this.orderService.saveForRibbon(userId,productId);
    }

    @RequestMapping("saveforfeign")
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object saveforFeign(@RequestParam("user_id") int userId,@RequestParam("product_id") int productId){
        return  this.orderService.saveForFeign(userId,productId);
    }

    // 方法引數簽名必須與api一致
    private Object saveOrderFail(int userId, int productId){
        // 監控報警機制
        new Thread(()->{
            String saveOrderKey = "save-order";
            String sendValue = redisTemplate.opsForValue().get(saveOrderKey);

            if(StringUtils.isBlank(sendValue)){
                // 傳送警告訊息
                System.out.println("緊急訊息,使用者下單失敗,請儘快處理查詢原因.");
                redisTemplate.opsForValue().set(saveOrderKey, "save-order-fali", 30, TimeUnit.SECONDS);
            } else {
                System.out.println("已經發送訊息,30秒內不可重複傳送。");
            }
        }).start();

        Map<String,Object> fallbackResponse = new HashMap();
        fallbackResponse.put("code", -100);
        fallbackResponse.put("msg","請求人數過多,請稍後再試。");
        return fallbackResponse;
    }
}

說明:在訂單服務呼叫產品服務出現熔斷的處理過程,上面還使用redis作為檢查一段時間內是否以及傳送監控通知資訊,熔斷後直接返回兜底資料,防止整個鏈路出現死等。hystrix主要就是通過@HystrixCommand進行使用。

feign結合Hystrix使用

我們可以通過檢視feign的pom可以發現feign已經集合了Hystrix,預設情況下是關閉的,那麼如何實現feign上使用Hystrix呢?

1.pom引入Hystrix依賴,這一步是必須要的
2.檢視@FeignClient原始碼

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.cloud.openfeign;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {
    @AliasFor("name")
    String value() default "";

    /** @deprecated */
    @Deprecated
    String serviceId() default "";

    @AliasFor("value")
    String name() default "";

    String qualifier() default "";

    String url() default "";

    boolean decode404() default false;

    Class<?>[] configuration() default {};

    Class<?> fallback() default void.class;

    Class<?> fallbackFactory() default void.class;

    String path() default "";

    boolean primary() default true;
}

我們可以看到上面有一個fallback和fallbackFactory屬性,其實我們就可以實現一個fallback類去處理FeignClient中fallback的情況。
3.實現ProductService的客戶端呼叫時fallback處理

package com.ckmike.order_service.fallback;

import com.ckmike.order_service.service.ProductClient;
import org.springframework.stereotype.Component;

/**
 * ProductServiceFallBack 簡要描述
 * <p> TODO:描述該類職責 </p>
 *
 * @author ckmike
 * @version 1.0
 * @date 18-11-23 下午2:04
 * @copyright ckmike
 **/
@Component
public class ProductServiceFallBack implements ProductClient {

    @Override
    public String findById(int id) {
        System.out.println("產品服務呼叫失敗!!!!!");
        System.out.println("呼叫監控訊息元件進行訊息傳送。");
        return null;
    }
}

package com.ckmike.order_service.service;

import com.ckmike.order_service.fallback.ProductServiceFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @ClassName ProductClient產品服務客戶端
 * @Description TODO:描述該介面職責
 * @Author ckmike
 * @Date 18-11-22 下午4:10
 * @Version 1.0
 * @Copyright ckmike
 **/
@FeignClient(name="product-service", fallback = ProductServiceFallBack.class)
public interface ProductClient {

    @GetMapping("/api/v1/product/find")
    String findById(@RequestParam(value = "id") int id);
}

4.配置開啟feign中hystrix(預設情況下是關閉的)

#feign元件的配置
feign:
  #預設是關閉的
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeOut: 2000
        readTimeOut: 2000

總結

1.hystrix能夠保護呼叫方和被呼叫方,防止請求鏈路因為某一個服務失敗而產生雪崩效應。
2.hystrix的隔離熔斷策略有執行緒、訊號量兩種方式,具體可檢視原始碼
3.熔斷器中實現監控是非常有用且非常有必要的,對於運營與維護具有重大意義。

關於SpringCloud相關部落格的原始碼,在我碼雲上已經上傳,有需要的可以檢視SpringCloud專案原始碼