【Spring Cloud Hystrix】【一】:服務容錯快速入門

一、Why服務容錯

       在微服務架構中,需要將系統拆分成多個服務單元,各單元的應用間通過服務註冊與訂閱的方式相互依賴。由於服務之間通過遠程過程調用RPC的方式執行,就有可能因爲網絡原因或者依賴服務自身問題造成調用失敗或延遲,而這些問題會直接導致調用方的對外服務也出現延遲,若此時調用方的請求不斷增加,最後就會因等待出現故障的依賴方響應延遲造成任務積壓,最終導致自身服務的癱瘓。

        舉個例子,我們的系統中分爲A,B,C等服務單元。用戶的調用鏈爲:User -> A -> B -> C。在用戶User請求A的時候,A回去請求B,B去請求C,當服務C因爲自身處理邏輯以及網絡原因導致響應緩慢,會直接導致服務B中請求C的線程被阻塞,接連導致A中線程阻塞,在漫長的等待過程中,User會得到調用失敗的結果。如果在高併發情況之下,因爲下游服務C故障而影響上游服務,將A,B服務"拖死",導致不可用。

       在微服務架構中,存在着那麼多的服務單元,若一個單元出現故障,就很容易因依賴關係而引發故障的蔓延,最終導致整個系統的癱瘓,這樣的架構相較於傳統架構更加不穩定。爲了解決這些問題,就產升了服務容錯保護機制等組件。而在SpringCloud中,這個強大的組件就是Hystrix,下面會通過搭建服務介紹hystrix的使用,包括超時設置,降級處理等。

二、快速入門

2.1 Consumer構建

首選要在consumer工程pom文件中引入hystrix組件:

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

工程主類ConsumerApplication中使用@EnableCircuitBreaker註解來開啓斷路器功能:

EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrix
@SpringBootApplication(exclude = PageHelperAutoConfiguration.class)
public class ConsumerApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
        System.out.println("ヾ(◍°∇°◍)ノ゙    Spring Boot Application Boot SUCCESS   ヾ(◍°∇°◍)ノ゙\n" +
                " ______                    _   ______            \n" +
                "|_   _ \\                  / |_|_   _ `.          \n" +
                "  | |_) |   .--.    .--. `| |-' | | `. \\  .--.   \n" +
                "  |  __'. / .'`\\ \\/ .'`\\ \\| |   | |  | |/ .'`\\ \\ \n" +
                " _| |__) || \\__. || \\__. || |, _| |_.' /| \\__. | \n" +
                "|_______/  '.__.'  '.__.' \\__/|______.'  '.__.'  ");
    }

    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        // 注意這裏要指向原先用main方法執行的Application啓動類
        return builder.sources(ConsumerApplication.class);
    }

}

ConsumerController定義:

@RestController
@RequestMapping("/springcloud/consumer/hystrix")
public class HystrixController extends BaseController {

    @Resource
    private HelloService helloService;

    @GetMapping("/timeout")
    public String hystrixTimeout() {

        String resStr = helloService.hello();

        System.out.println(resStr);

        return success(resStr);
    }
}

HelloService接口定義:

public interface HelloService {
    String hello();
}

HelloServiceImpl實現:

@Service
public class HelloServiceImpl implements HelloService {

    @Resource
    private HelloFeign helloFeign;

    @Override
    @HystrixCommand(commandKey = "testKey", groupKey = "testGroup")
    public String hello() {
        return helloFeign.hello();
    }
}

FeignClient定義:

@FeignClient(name = "provider-service")
public interface HelloFeign {

    @GetMapping(value = "/springcloud/privoder/hello")
    String hello();
}

hystrix配置文件:

hystrix:
  threadpool:
    testGroup:
      coreSize: 20
      maximumSize: 100
      allowMaximumSizeToDivergeFromCoreSize: true
      maxQueueSize: 200
      queueSizeRejectionThreshold: 1000
  command:
    testKey:
      execution:
        timeout:
          enabled: true
        isolation:
          strategy: THREAD
          thread:
            timeoutInMilliseconds: 1000
            interruptOnTimeout: true
            interruptOnFutureCancel: false
          semaphore:
            maxConcurrentRequests: 5000

2.2 Provider構建

 

 

@Slf4j
@RestController
@RequestMapping("/springcloud/provider")
public class ProviderController extends BaseController {
    
    @GetMapping(value = "/hello")
    public String hello() throws Exception{

        //讓處理線程隨機等待sleepTime毫秒
        int sleepTime = new Random().nextInt(3000);
        Thread.sleep(sleepTime);
        System.out.println("elapse time = " + sleepTime);
        return success("hello hystrix elapse " + sleepTime);
    }
}

2.3 演練

生產者模擬超時處理時間爲0~3000ms,消費者請求的超時時間爲1000ms,參數爲:timeoutInMilliseconds,通過多次請求消費者,可以觀察到兩種結果:

1.返回結果正常,返回碼200,響應時間<1000ms

{"errno":0,"data":{},"errmsg":"{\"errno\":0,\"data\":{},\"errmsg\":\"hello hystrix elapse 774\"}"}

2.返回結果異常,返回碼500,響應時間>1000ms

{
    "timestamp": "2020-01-05T07:10:39.470+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "testKey timed-out and fallback failed.",
    "trace": "com.netflix.hystrix.exception.HystrixRuntimeException:",
    "path": "//springcloud/consumer/hystrix/timeout"
}

三、超時設定及服務降級

       有時候我們需要捕獲異常情況,並返回自定義的信息給上游,也是所謂的"服務降級"。fallback是Hystrix命令執行失敗時使用後備方法,用來實現服務的降級處理邏輯。通過@HystrixCommand中的fallbackMethod參數來指定具體的服務降級實現方法。

@Service
public class HelloServiceImpl implements HelloService {

    @Resource
    private HelloFeign helloFeign;

    @Override
    @HystrixCommand(fallbackMethod = "helloFallback", commandKey = "testKey", groupKey = "testGroup")
    public String hello() {
        return helloFeign.hello();
    }

    public String helloFallback() {
        return "hello fallback";
    }
}

在使用註解來定義服務降級邏輯時,我們需要將具體的Hystrix命令與fallback實現函數定義在同一個類中,並且fallbackMethod的值必須與實現fallback方法的名字相同。由於必須定義在一個類中,所以對於fallback的訪問修飾符沒有特定的要求,定義爲private,public,protected都行。

異常返回結果爲(>1000ms):

{"errno":0,"data":{},"errmsg":"hello fallback"}

Author:憶之獨秀

Email:[email protected]

轉載註明出處:https://blog.csdn.net/lavorange/article/details/103843058

             

發佈了130 篇原創文章 · 獲贊 114 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章