「接口熔断java」接口熔断和降级

博主:adminadmin 2022-11-28 04:16:05 49

本篇文章给大家谈谈接口熔断java,以及接口熔断和降级对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java 如何实现服务熔断

用length()方法、charAt方法结合for循环就行了,

package com.golden.test;

public class TestString {

public static void main(String[] args) {

String str = "你叫神马?我叫Tesson.";

for (int i = 0; i str.length(); i++) {

char item = str.charAt(i);

System.out.println(item);

}

}

}

自定义springcloud-gateway熔断处理

一、场景

使用spring cloud gateway后,有了熔断,问题也就随之而来,服务间调用有了hystrix可以及时的排除坏接口、坏服务的问题,对系统很有帮助。但是!不是所有的接口都是极短时间内完成的,不是所有的接口都可以设置一样的超时时间的!

那么我们面临一个问题,那就是百分之99的接口都可以在1s内完美完成,但是就是那几个特殊接口,需要十几秒,几十秒的等待时间,而默认熔断的时间又只有一个。

二、分析

在前面 springcloudgateway源码解析之请求篇 中我们知道请求会经过一些列的过滤器(GatewayFilter),而springcloudgateway的降级熔断处理就是由一个特殊的过滤器来处理的,通过源码分析我们关注到HystrixGatewayFilterFactory这个类,这个类的作用就是生产GatewayFilter用的,我们看下它的实现

可以看到红框处最后构建了一个匿名的GatewayFilter对象返回,这个对象在接口请求过程中会被加载到过滤器链条中,仔细看到 这里是创建了一个RouteHystrixCommand这个命令对象,最终调用command.toObservable()方法处理请求,如果超时熔断调用resumeWithFallback方法

通过源码分析 gateway在路由时可以指定HystrixCommandKey,并且对HystrixCommandKey设置超时时间

三、方案

知道网关熔断的原理就好办了,自定义熔断的过滤器配置到接口请求过程中,由过滤器来读取接口熔断配置并构建HystrixObservableCommand处理请求。

自定义一个类XXXGatewayFilterFactory继承AbstractGatewayFilterFactory,将api和对应的timeout配置化,来实现细化到具体接口的熔断配置,具体实现如下:

package org.unicorn.framework.gateway.filter;

import cn.hutool.core.collection.CollectionUtil;

import com.netflix.hystrix.HystrixCommandGroupKey;

import com.netflix.hystrix.HystrixCommandKey;

import com.netflix.hystrix.HystrixCommandProperties;

import com.netflix.hystrix.HystrixObservableCommand;

import com.netflix.hystrix.exception.HystrixRuntimeException;

import org.springframework.beans.factory.ObjectProvider;

import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;

import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;

import org.springframework.cloud.gateway.support.TimeoutException;

import org.springframework.core.annotation.AnnotatedElementUtils;

import org.springframework.http.server.reactive.ServerHttpRequest;

import org.springframework.stereotype.Component;

import org.springframework.util.AntPathMatcher;

import org.springframework.web.bind.annotation.ResponseStatus;

import org.springframework.web.reactive.DispatcherHandler;

import org.springframework.web.server.ResponseStatusException;

import org.springframework.web.server.ServerWebExchange;

import org.springframework.web.util.UriComponentsBuilder;

import reactor.core.publisher.Mono;

import rx.Observable;

import rx.RxReactiveStreams;

import rx.Subscription;

import java.net.URI;

import java.util.Collections;

import java.util.List;

import java.util.function.Function;

/**

* @Author: xiebin

* @Description:

* @Date:Create:in 2022-07-06 9:17

*/

@Component

public class UnicornHystrixGatewayFilterFactoryextends AbstractGatewayFilterFactory {

private static final StringNAME ="unicornHystrix";

    private ObjectProviderdispatcherHandlerProvider;

    private AntPathMatcherantPathMatcher;

    public UnicornHystrixGatewayFilterFactory(ObjectProvider dispatcherHandlerProvider) {

super(Config.class);

        this.dispatcherHandlerProvider = dispatcherHandlerProvider;

        this.antPathMatcher =new AntPathMatcher();

    }

@Override

    public ListshortcutFieldOrder() {

return Collections.singletonList(NAME_KEY);

    }

/**

* 获取服务ID

*

    * @param exchange

    * @return

    */

    public StringserviceId(ServerWebExchange exchange) {

ServerHttpRequest request = exchange.getRequest();

        String path = request.getPath().pathWithinApplication().value();

        try {

path = path.split("/")[1];

            return path;

        }catch (Exception e) {

return "default";

        }

}

/**

    * @param key

    * @param timeout

    * @return

    */

    private HystrixObservableCommand.SetterinitSetter(String key, Integer timeout) {

HystrixObservableCommand.Setter setter = HystrixObservableCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(key)).andCommandKey(HystrixCommandKey.Factory.asKey(key));

        if (timeout !=null) {

setter.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(timeout));

        }

return setter;

    }

/**

    * @param exchange

    * @param chain

    * @param config

    * @return

    */

    private UnicornRouteHystrixCommandinitUnicornRouteHystrixCommand(ServerWebExchange exchange, GatewayFilterChain chain, Config config) {

//路由配置的超时设置

        List apiTimeoutList = config.getTimeouts();

        ServerHttpRequest request = exchange.getRequest();

        String path = request.getPath().pathWithinApplication().value();

        UnicornRouteHystrixCommand command;

        if (CollectionUtil.isNotEmpty(apiTimeoutList)) {

//request匹配属于那种模式

            ApiHystrixTimeout apiHystrixTimeout = getApiHystrixTimeout(apiTimeoutList, path);

            command =new UnicornRouteHystrixCommand(config.getFallbackUri(), exchange, chain, initSetter(apiHystrixTimeout.getApiPattern(), apiHystrixTimeout.getTimeout()));

        }else {

command =new UnicornRouteHystrixCommand(config.getFallbackUri(), exchange, chain, initSetter(serviceId(exchange), null));

        }

return command;

    }

/**

    * @param apiTimeoutList

    * @param path

    * @return

    */

    private ApiHystrixTimeoutgetApiHystrixTimeout(List apiTimeoutList, String path) {

for (ApiHystrixTimeout apiTimeoutPattern : apiTimeoutList) {

if (this.antPathMatcher.match(apiTimeoutPattern.getApiPattern(), path)) {

return apiTimeoutPattern;

            }

}

ApiHystrixTimeout apiHystrixTimeout =new ApiHystrixTimeout();

        apiHystrixTimeout.setApiPattern("default");

        apiHystrixTimeout.timeout =null;

        return apiHystrixTimeout;

    }

@Override

    public GatewayFilterapply(Config config) {

return (exchange, chain) - {

UnicornRouteHystrixCommand command = initUnicornRouteHystrixCommand(exchange, chain, config);

            return Mono.create(s - {

Subscription sub =command.toObservable().subscribe(s::success, s::error, s::success);

                s.onCancel(sub::unsubscribe);

            }).onErrorResume((Function) throwable - {

if (throwableinstanceof HystrixRuntimeException) {

HystrixRuntimeException e = (HystrixRuntimeException) throwable;

                    HystrixRuntimeException.FailureType failureType = e.getFailureType();

                    switch (failureType) {

case TIMEOUT:

return Mono.error(new TimeoutException());

                        case COMMAND_EXCEPTION: {

Throwable cause = e.getCause();

                            if (causeinstanceof ResponseStatusException || AnnotatedElementUtils

.findMergedAnnotation(cause.getClass(), ResponseStatus.class) !=null) {

return Mono.error(cause);

                            }

}

default:

break;

                    }

}

return Mono.error(throwable);

            }).then();

        };

    }

@Override

    public Stringname() {

return NAME;

    }

private class UnicornRouteHystrixCommandextends HystrixObservableCommand {

private final URIfallbackUri;

        private final ServerWebExchangeexchange;

        private final GatewayFilterChainchain;

        /**

        * @param fallbackUri

        * @param exchange

        * @param chain

        */

        public UnicornRouteHystrixCommand(URI fallbackUri, ServerWebExchange exchange, GatewayFilterChain chain, HystrixObservableCommand.Setter setter) {

super(setter);

            this.fallbackUri = fallbackUri;

            this.exchange = exchange;

            this.chain = chain;

        }

@Override

        protected Observableconstruct() {

return RxReactiveStreams.toObservable(this.chain.filter(exchange));

        }

@Override

        protected ObservableresumeWithFallback() {

if (null ==fallbackUri) {

return super.resumeWithFallback();

            }

URI uri =exchange.getRequest().getURI();

            boolean encoded = ServerWebExchangeUtils.containsEncodedParts(uri);

            URI requestUrl = UriComponentsBuilder.fromUri(uri)

.host(null)

.port(null)

.uri(this.fallbackUri)

.build(encoded)

.toUri();

            exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);

            ServerHttpRequest request =this.exchange.getRequest().mutate().uri(requestUrl).build();

            ServerWebExchange mutated =exchange.mutate().request(request).build();

            DispatcherHandler dispatcherHandler = UnicornHystrixGatewayFilterFactory.this.dispatcherHandlerProvider.getIfAvailable();

            return RxReactiveStreams.toObservable(dispatcherHandler.handle(mutated));

        }

}

public static class ApiHystrixTimeout {

public StringgetApiPattern() {

return apiPattern;

        }

public void setApiPattern(String apiPattern) {

this.apiPattern = apiPattern;

        }

public IntegergetTimeout() {

return timeout;

        }

public void setTimeout(Integer timeout) {

this.timeout = timeout;

        }

private StringapiPattern;

        private Integertimeout;

    }

public static class Config {

private Stringid;

        private URIfallbackUri;

        /**

* url - timeout ms

*/

        private Listtimeouts;

        public StringgetId() {

return id;

        }

public ConfigsetId(String id) {

this.id = id;

return this;

        }

public URIgetFallbackUri() {

return fallbackUri;

        }

public ConfigsetFallbackUri(URI fallbackUri) {

if (fallbackUri !=null !"forward".equals(fallbackUri.getScheme())) {

throw new IllegalArgumentException("Hystrix Filter currently only supports 'forward' URIs, found " + fallbackUri);

            }

this.fallbackUri = fallbackUri;

return this;

        }

public ListgetTimeouts() {

return timeouts;

        }

public ConfigsetTimeouts(List timeouts) {

this.timeouts = timeouts;

return this;

        }

}

}

配置示例

spring.cloud.gateway.default-filters[0].name=unicornHystrix

spring.cloud.gateway.default-filters[0].args.fallbackUri=forward:/defaultFallback

spring.cloud.gateway.default-filters[0].args.timeouts[0].apiPattern=/gf-oss-service//oss/part/upload

spring.cloud.gateway.default-filters[0].args.timeouts[0].timeout=100000

java springcloud中为什么用熔断,不用异常机制?

一个微服务的超时失败可能导致瀑布式连锁反映,当对某个微服务的调用失败达到一个特定的阀值(5秒之内发生20次失败是Hystrix定义的缺省值), 链路就会被处于open状态, 之后所有所有对这个微服务的调用都不会被执行。

超时是靠异常捕获的,熔断是一个调度管理机制。

关于接口熔断java和接口熔断和降级的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

The End

发布于:2022-11-28,除非注明,否则均为首码项目网原创文章,转载请注明出处。