Hystrix使用分析

Hystrix使用

使用Hystrix實現(xiàn)熔斷

要實現(xiàn)熔斷,首先需要在請求調(diào)用方pom文件中加入

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

在啟動類上加入@EnableCircuitBreaker注解,并在調(diào)用到另一個微服務的方法上加入一些配置

 @GetMapping("/checkHystrix/{userId}")
    @HystrixCommand(threadPoolKey = "checkHystrix1",
    threadPoolProperties = {
            @HystrixProperty(name = "coreSize",value = "1"),
            @HystrixProperty(name = "maxQueueSize",value = "20")
    },
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000")
    })
    public Integer checkHystrix(@PathVariable Long userId) {
        String url = "http://zhao-service-resume/resume/openstate/"+userId;
        Integer forObject =
                restTemplate.getForObject(url, Integer.class);
        return forObject;
    }

將調(diào)用到的服務中加入線程休眠十秒。訪問上述服務,在界面上即可發(fā)現(xiàn)Hystrix的超時錯誤


file

服務降級

在配置中再增加一個 fallbackMethod = "customeFallback",
配置降級兜底方法的具體形式是

    public  Integer customeFallback(Long userId){
        return -1;
    }

當某個服務熔斷之后,服務器將不再被調(diào)?,此刻客戶端可以??準備?個本地的fallback回調(diào),返回?個缺省值,這樣做,雖然服務?平下降,但好?可?,?直接掛掉要強。但是在配置服務降級策略時,降級(兜底)?法必須和被降級?法相同的?法簽名(相同參數(shù)列表、相同返回值)
如果參數(shù)不同會出現(xiàn)com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException: fallback method wasn't found: customeFallback([class java.lang.Long])
如果返回值不同會出現(xiàn)。且包裝類和基本類型不能共用
Hint: Fallback method 'public int com.zp.controller.AutoDeliverController.customeFallback(java.lang.Long)' must return: class java.lang.Integer or its subclass

倉壁模式(線程池隔離模式)

如果不進?任何線程池設置,所有熔斷?法使??個Hystrix線程池(默認為10個線程),那么這樣的話會導致問題,這個問題并不是扇出鏈路微服務不可?導致的,?是我們的線程機制導致的,如果?法A的請求把10個線程都?了,?法2請求處理的時候壓根都、沒法去訪問B,因為沒有線程可?,并不是B服務不可?。因此在配置Hystrix線程時,多個方法應該寫多個線程池。這樣能夠讓線程之間互不影響

  @GetMapping("/checkHystrix/{userId}")
    @HystrixCommand(threadPoolKey = "checkHystrix1",
    threadPoolProperties = {
            @HystrixProperty(name = "coreSize",value = "1"),
            @HystrixProperty(name = "maxQueueSize",value = "20")
    },
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000")
    })
    public Integer checkHystrix(@PathVariable Long userId) {
        String url = "http://zhao-service-resume/resume/openstate/"+userId;
        Integer forObject =
                restTemplate.getForObject(url, Integer.class);
        return forObject;
    }

    @GetMapping("/checkHystrixFallback/{userId}")
    @HystrixCommand(threadPoolKey = "checkHystrix2",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize",value = "2"),
                    @HystrixProperty(name = "maxQueueSize",value = "20")
            },
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000")
            },
            fallbackMethod = "customeFallback"


    )

通過postman發(fā)送批量請求,并通過jstack命令可以看到兩個方法的線程池進行了隔離


file

其他屬性的含義

            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000"),
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value="50"),
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value="3000")
            }

metrics.rollingStats.timeInMilliseconds該屬性是下面的熔斷的統(tǒng)計時間窗口定義
circuitBreaker.requestVolumeThreshold該屬性統(tǒng)計時間窗?內(nèi)的失敗的次數(shù),達到此次數(shù)之后開啟熔斷操作
circuitBreaker.errorThresholdPercentage 窗口內(nèi)失敗的次數(shù)的百分比,達到這個百分比之后開啟熔斷操作
circuitBreaker.sleepWindowInMilliseconds 熔斷多久間隔多久以后開始嘗試是否恢復

源碼簡要分析

首先我們根據(jù)注解類@EnableCircuitBreaker可以找到SpringFactoryImportSelector類,該類通過泛型在spring.factories文件中找到注解了該泛型的配置類

@Override
    public String[] selectImports(AnnotationMetadata metadata) {
        if (!isEnabled()) {
            return new String[0];
        }
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                metadata.getAnnotationAttributes(this.annotationClass.getName(), true));

        Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is "
                + metadata.getClassName() + " annotated with @" + getSimpleName() + "?");

        // Find all possible auto configuration classes, filtering duplicates
        List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader
                .loadFactoryNames(this.annotationClass, this.beanClassLoader)));

        if (factories.isEmpty() && !hasDefaultFactory()) {
            throw new IllegalStateException("Annotation @" + getSimpleName()
                    + " found, but there are no implementations. Did you forget to include a starter?");
        }

        if (factories.size() > 1) {
            // there should only ever be one DiscoveryClient, but there might be more than
            // one factory
            log.warn("More than one implementation " + "of @" + getSimpleName()
                    + " (now relying on @Conditionals to pick one): " + factories);
        }

        return factories.toArray(new String[factories.size()]);
    }

隨后在spring.factories中找到了加載的配置類

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

配置類中配置了一個切面HystrixCommandAspect,Hystrix實現(xiàn)的主要功能都在這個切面中進行了執(zhí)行

    public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = getMethodFromTarget(joinPoint);
        Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
        if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
            throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
                    "annotations at the same time");
        }
        MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
        MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
        HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
        ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
                metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

        Object result;
        try {
            if (!metaHolder.isObservable()) {
                result = CommandExecutor.execute(invokable, executionType, metaHolder);
            } else {
                result = executeObservable(invokable, executionType, metaHolder);
            }
        } catch (HystrixBadRequestException e) {
            throw e.getCause();
        } catch (HystrixRuntimeException e) {
            throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
        }
        return result;
    }

使用同步調(diào)用會走executeObservable最終進入HystrixCommand進入最終的處理邏輯

    public R execute() {
        try {
            return queue().get();
        } catch (Exception e) {
            throw Exceptions.sneakyThrow(decomposeException(e));
        }
    }

進入執(zhí)行隊列并異步獲取
最后執(zhí)行 final Future<R> delegate = toObservable().toBlocking().toFuture();具體Hystrix中的熔斷降級操作即在toObservable()完成

歡迎關(guān)注和點贊,以及總結(jié)的分類面試題https://github.com/zhendiao/JavaInterview

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • hystrix是什么? 在微服務場景中,通常會有很多層的服務調(diào)用。如果一個底層服務出現(xiàn)問題,故障會被向上傳播給用戶...
    段永平閱讀 468評論 0 0
  • 原文:https://my.oschina.net/7001/blog/1619842 摘要: Hystrix是N...
    laosijikaichele閱讀 4,461評論 0 25
  • Hystrix Hystrix 是用于處理延遲和容錯的開源庫; Hystrix 主要用于避免級聯(lián)故障,提高系統(tǒng)彈性...
    烏魯木齊001號程序員閱讀 1,879評論 0 1
  • 全文概覽 [TOC] 為什么需要hystrix hystrix官網(wǎng)地址github[https://github....
    zxhtom閱讀 816評論 0 2
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,931評論 2 7

友情鏈接更多精彩內(nèi)容