All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j.Resilience4jRetrofitDegrade Maven / Gradle / Ivy

The newest version!
package com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j;

import com.github.lianjiatech.retrofit.spring.boot.degrade.BaseRetrofitDegrade;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitBlockException;
import com.github.lianjiatech.retrofit.spring.boot.util.AnnotationExtendUtils;
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.core.StopWatch;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.core.annotation.AnnotatedElementUtils;
import retrofit2.Invocation;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author 陈添明
 * @since 2022/5/1 8:02 下午
 */
public class Resilience4jRetrofitDegrade extends BaseRetrofitDegrade {

    protected final CircuitBreakerRegistry circuitBreakerRegistry;
    protected final GlobalResilience4jDegradeProperty globalResilience4jDegradeProperty;
    protected final CircuitBreakerConfigRegistry circuitBreakerConfigRegistry;

    public Resilience4jRetrofitDegrade(CircuitBreakerRegistry circuitBreakerRegistry,
            GlobalResilience4jDegradeProperty globalResilience4jDegradeProperty,
            CircuitBreakerConfigRegistry circuitBreakerConfigRegistry) {
        this.circuitBreakerRegistry = circuitBreakerRegistry;
        this.globalResilience4jDegradeProperty = globalResilience4jDegradeProperty;
        this.circuitBreakerConfigRegistry = circuitBreakerConfigRegistry;
    }

    @Override
    public boolean isEnableDegrade(Class retrofitInterface) {
        if (globalResilience4jDegradeProperty.isEnable()) {
            Resilience4jDegrade resilience4jDegrade =
                    AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, Resilience4jDegrade.class);
            if (resilience4jDegrade == null) {
                return true;
            }
            return resilience4jDegrade.enable();
        } else {
            return AnnotationExtendUtils.isAnnotationPresentIncludeMethod(retrofitInterface, Resilience4jDegrade.class);
        }
    }

    @Override
    public void loadDegradeRules(Class retrofitInterface) {
        for (Method method : retrofitInterface.getMethods()) {
            if (isDefaultOrStatic(method)) {
                continue;
            }
            Resilience4jDegrade resilience4jDegrade =
                    AnnotationExtendUtils.findMergedAnnotation(method, retrofitInterface, Resilience4jDegrade.class);
            if (!needDegrade(resilience4jDegrade)) {
                continue;
            }
            String circuitBreakerConfigName =
                    resilience4jDegrade == null ? globalResilience4jDegradeProperty.getCircuitBreakerConfigName()
                            : resilience4jDegrade.circuitBreakerConfigName();
            circuitBreakerRegistry.circuitBreaker(parseResourceName(method, retrofitInterface),
                    circuitBreakerConfigRegistry.get(circuitBreakerConfigName));
        }
    }

    protected boolean needDegrade(Resilience4jDegrade resilience4jDegrade) {
        if (globalResilience4jDegradeProperty.isEnable()) {
            if (resilience4jDegrade == null) {
                return true;
            }
            return resilience4jDegrade.enable();
        } else {
            return resilience4jDegrade != null && resilience4jDegrade.enable();
        }
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Invocation invocation = request.tag(Invocation.class);
        if (invocation == null) {
            return chain.proceed(request);
        }
        CircuitBreaker circuitBreaker =
                circuitBreakerRegistry.find(parseResourceName(invocation.method(), invocation.service())).orElse(null);
        if (Objects.isNull(circuitBreaker)) {
            // 断路器为空则直接调用返回
            return chain.proceed(request);
        }
        StopWatch stopWatch = StopWatch.start();
        try {
            circuitBreaker.acquirePermission();
            Response response = chain.proceed(request);
            circuitBreaker.onResult(stopWatch.stop().toNanos(), TimeUnit.NANOSECONDS, response);
            return response;
        } catch (CallNotPermittedException e) {
            throw new RetrofitBlockException(e);
        } catch (Throwable throwable) {
            circuitBreaker.onError(stopWatch.stop().toNanos(), TimeUnit.NANOSECONDS, throwable);
            throw throwable;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy