欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于SpringCloud手寫一個(gè)簡(jiǎn)易版Sentinel

 更新時(shí)間:2021年05月20日 09:37:57   作者:唐宋xy  
SpringCloud Alibaba Sentinel是當(dāng)前最為流行一種熔斷降級(jí)框架,簡(jiǎn)單易用的方式可以快速幫助我們實(shí)現(xiàn)服務(wù)的限流和降級(jí),保證服務(wù)的穩(wěn)定性。

Sentinel 是什么?

隨著微服務(wù)的流行,服務(wù)和服務(wù)之間的穩(wěn)定性變得越來越重要。Sentinel 以流量為切入點(diǎn),從流量控制、熔斷降級(jí)、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性。

不可否認(rèn)的是,Sentinel功能豐富,并且在提供好用的dashboard提供配置,但是Sentinel在集成到項(xiàng)目中時(shí)需要引入多個(gè)依賴,并且需要閱讀相關(guān)文檔,以及dashboard中的相關(guān)配置才可以接入到項(xiàng)目中,這個(gè)過程還是較為復(fù)雜的。

如果我們的項(xiàng)目并不需要這么多的功能,只是需要當(dāng)某個(gè)方法或者某個(gè)功能發(fā)生異常的時(shí)候可以實(shí)現(xiàn)降級(jí),并不是直接中斷程序,該業(yè)務(wù)功能不是主流程,那么我們?yōu)榱藢?shí)現(xiàn)這樣一個(gè)小功能的時(shí)候,將Sentinel集成到項(xiàng)目中的過程顯然是較為復(fù)雜的,那么這個(gè)時(shí)候,就需要我們實(shí)現(xiàn)一個(gè)簡(jiǎn)答的功能降級(jí)的通用方式,下面就一起看看一個(gè)簡(jiǎn)易版的Sentinel的實(shí)現(xiàn)

當(dāng)然,實(shí)現(xiàn)這個(gè)功能,只需要一個(gè)try-catch就可以搞定個(gè),但是我們需要的是try-catch嗎?No! 我們需要的是優(yōu)雅~ 我想你也不想看到滿屏的try-catch吧,如果哪天這個(gè)方法無需降級(jí)的時(shí)候,再去一行一行刪代碼嗎?

示例代碼已收錄到Github: github.com/chenliang15…

定義注解

第一步,定義一個(gè)通用注解,這個(gè)注解可以幫助我們無侵入性的實(shí)現(xiàn)功能降級(jí),并且提供豐富的屬性,讓注解的通用性和靈活性更強(qiáng)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface DegradeResource {

    // 降級(jí)的方法名稱
    String fallback();
	
    // 降級(jí)的類名稱,可選
    Class<?>[] fallbackClass() default {};

    // 指定降級(jí)異常,可選
    Class<? extends Throwable>[] exceptionHandle() default {};

}
  • fallback:降價(jià)方法的名稱,需要指定降級(jí)方法的名稱,才可以在發(fā)生異常時(shí)調(diào)用降級(jí)方法,必選參數(shù)。

降級(jí)方法須知:

必須為public
方法返回類型、方法參數(shù)必須和原始方法保持一致,最后一個(gè)參數(shù)允許多一個(gè)Throwable,用來接收發(fā)生的異常

  • fallbackClass:指定降級(jí)方法所在的class,可選參數(shù),如果不指定則默認(rèn)降級(jí)方法在當(dāng)前class中
  • exceptionHandle:指定異常處理,當(dāng)發(fā)生指定的異常時(shí)才選擇進(jìn)行降級(jí),可選參數(shù),數(shù)組類型,可以接收多個(gè)異常類型

定義切面處理器

當(dāng)資源降級(jí)注解定義之后,我們就需要一個(gè)切面處理器,對(duì)定義的降級(jí)注解做切面處理,當(dāng)調(diào)用的方法上有@DegradeResource注解時(shí),會(huì)通過切面處理器進(jìn)行處理

@Aspect
public class DegradeResourceAspect {


    @Around("@annotation(degradeResource)")
    public Object doAround(ProceedingJoinPoint pjp, DegradeResource degradeResource) throws Throwable {
        try {
            return pjp.proceed();
        } catch(Throwable e){
            // need to trace exception list
            Class<? extends Throwable>[] exceptions = degradeResource.exceptionHandle();
            if(exceptions.length > 0) {
                List<Class<? extends Throwable>> exceptionList = Arrays.asList(exceptions);
                // 判斷是否為同一個(gè)個(gè)異常
                if (exceptionBelongTo(e, exceptionList)) {
                    return handleFallbackMethod(pjp, degradeResource, e);
                } else {
                    throw e;
                }
            }
            return handleFallbackMethod(pjp, degradeResource, e);
        }
    }

    /**
     * if the throw exception is belong to exception trace list
     *
     * @param e
     * @param exceptionList
     * @return
     */
    private boolean exceptionBelongTo(Throwable e, List<Class<? extends Throwable>> exceptionList) {
        for (Class<? extends Throwable> aClass : exceptionList) {
            if(aClass.isAssignableFrom(e.getClass())) {
                return true;
            }
        }
        return false;
    }

    /**
     * invoke fallback method
     *
     */
    private Object handleFallbackMethod(ProceedingJoinPoint pjp, DegradeResource degradeResource, Throwable e) throws Throwable {
        // fallback method
        String fallback = degradeResource.fallback();
        if(StringUtils.isEmpty(fallback)) {
            throw e;
        }
        // fallback class
        Class<?> clazz = degradeResource.fallbackClass().length > 0 ? degradeResource.fallbackClass()[0] : pjp.getTarget().getClass();

        // 獲取當(dāng)前執(zhí)行的方法名稱
        Method fallbackMethod = findFallbackMethod(pjp, clazz, fallback);
        if(Objects.isNull(fallbackMethod)) {
            throw e;
        }

        // fallback method args
        Object[] args;
        Object[] originArgs = pjp.getArgs();
        int paramCount = fallbackMethod.getParameterTypes().length;
        if(originArgs.length == paramCount) {
            args = originArgs;
        } else {
            // fill throwable to fallback method args
            args = Arrays.copyOf(originArgs, originArgs.length + 1);
            args[args.length - 1] = e;
        }

        // if static
        if(Modifier.isStatic(fallbackMethod.getModifiers())) {
            return fallbackMethod.invoke(null, args);
        }
        return fallbackMethod.invoke(clazz.newInstance(), args);
    }

    private Method findFallbackMethod(ProceedingJoinPoint pjp, Class<?> clazz, String fallbackName) {
        MethodSignature signers = (MethodSignature) pjp.getSignature();
        Class<?>[] originParams = signers.getParameterTypes();
        Class<?>[] paramsWithException = Arrays.copyOf(originParams, originParams.length + 1);
        paramsWithException[paramsWithException.length - 1] = Throwable.class;
        // find fallback method with origin params
        Method method = findMethod(clazz, originParams, fallbackName, signers.getReturnType());
        if(method == null) {
            // find fallback method with exception params
            method = findMethod(clazz, paramsWithException, fallbackName, signers.getReturnType());
        }
        return method;
    }

    private Method findMethod(Class<?> clazz, Class<?>[] paramsType, String fallbackName, Class<?> returnType) {
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if(method.getName().equals(fallbackName)
                && returnType.isAssignableFrom(method.getReturnType())
                && Arrays.equals(paramsType, method.getParameterTypes())) {
                return method;
            }
        }
        return null;
    }

}

總體的流程為:當(dāng)掃描到切面時(shí),第一步先正常執(zhí)行方法,當(dāng)方法發(fā)生異常時(shí),判斷當(dāng)前是否制定異常,如果沒有指定異常處理類型,那么就默認(rèn)走降級(jí)方法,如果當(dāng)前指定了降級(jí)的異常處理類型,那么就判斷當(dāng)前方法拋出的異常是否為需要處理的異常,如果是則調(diào)用降級(jí)方法,如果不是需要處理的異常,那么就拋出異常。

符合當(dāng)前場(chǎng)景的需要,簡(jiǎn)單化的異常降級(jí)

測(cè)試降級(jí)

總共測(cè)試了3中方式的異常降級(jí),分別為默認(rèn)所有異常降級(jí)、指定異常降級(jí)、指定降級(jí)方法的處理類

@Service
public class DegradeResourceTestService {


    @DegradeResource(fallback = "findByIdFromCacheFallback1")
    public String findById(String id) {
        int i = Integer.parseInt(id);
        System.out.println("id=" + id);
        return "ok = " + id;
    }

    @DegradeResource(fallback = "findByIdFromCacheFallback2", exceptionHandle = {NumberFormatException.class})
    public String findByIdWithException(String id) {
        int i = Integer.parseInt(id);
        System.out.println("id=" + id);
        return "ok = " + id;
    }

    /**
     * 支持指定fallback method的class,將降級(jí)方法統(tǒng)一放置指定的class中
     *
     */
    @DegradeResource(fallback = "findByIdFromCacheFallback3", exceptionHandle = {NumberFormatException.class},
            fallbackClass = {FallbackClassService.class})
    public String findByIdWithFallbackClass(String id) {
        int i = Integer.parseInt(id);
        System.out.println("id=" + id);
        return "ok = " + id;
    }


    /**
     * fallback method可以只接受原始函數(shù)的參數(shù)
     */
    public String findByIdFromCacheFallback1(String id) {
        return "fallback1 = " + id;
    }

    /**
     * fallback method 不僅可以接收原始方法的參數(shù),還可以接收具體的Exception
     *
     */
    public String findByIdFromCacheFallback2(String id, Throwable e) {
        System.out.println("fallback method exception:" + e);
        return "fallback2 = " + id;
    }

}

結(jié)果:

可以看到,當(dāng)發(fā)生異常時(shí),可以通過降級(jí)保證主流程的通常,對(duì)于非主流程的功能,我們可以通過@DegradeResource注解保證流程的完善和降級(jí)方案,保證用戶的體驗(yàn)和程序的正常。

以上就是基于SpringCloud手寫一個(gè)簡(jiǎn)易版Sentinel的詳細(xì)內(nèi)容,更多關(guān)于SpringCloud手寫Sentinel的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mac中IntelliJ IDEA 2019.1注冊(cè)過程分享

    Mac中IntelliJ IDEA 2019.1注冊(cè)過程分享

    這篇文章主要介紹了Mac中IntelliJ IDEA 2019.1注冊(cè)過程,本文給大家分享到腳本之家平臺(tái)供大家學(xué)習(xí),需要的朋友可以參考下
    2020-02-02
  • 淺談virtual、abstract方法和靜態(tài)方法、靜態(tài)變量理解

    淺談virtual、abstract方法和靜態(tài)方法、靜態(tài)變量理解

    下面小編就為大家?guī)硪黄獪\談virtual、abstract方法和靜態(tài)方法、靜態(tài)變量理解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java?棧與隊(duì)列實(shí)戰(zhàn)真題訓(xùn)練

    Java?棧與隊(duì)列實(shí)戰(zhàn)真題訓(xùn)練

    在編寫程序的時(shí)候,對(duì)于棧與隊(duì)列的應(yīng)用需要熟練的掌握,這樣才能夠確保寫出來的代碼有質(zhì)量。本文小編就以幾個(gè)題目詳細(xì)說說Java中的棧與隊(duì)列,需要的朋友可以參考一下
    2022-04-04
  • 如何獲取MyBatis Plus執(zhí)行的完整的SQL語句

    如何獲取MyBatis Plus執(zhí)行的完整的SQL語句

    這篇文章主要介紹了如何獲取MyBatis Plus執(zhí)行的完整的SQL語句問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java原裝代碼完成pdf在線預(yù)覽和pdf打印及下載

    java原裝代碼完成pdf在線預(yù)覽和pdf打印及下載

    本文主要介紹了java原裝代碼完成pdf在線預(yù)覽和pdf打印及下載的方法,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • 批量上傳Jar包到Maven私服的工具的方法

    批量上傳Jar包到Maven私服的工具的方法

    這篇文章主要介紹了批量上傳Jar包到Maven私服的工具的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • ssm項(xiàng)目session使用及其作用域問題

    ssm項(xiàng)目session使用及其作用域問題

    這篇文章主要介紹了ssm項(xiàng)目session使用及其作用域問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • SpringBoot封裝響應(yīng)處理超詳細(xì)講解

    SpringBoot封裝響應(yīng)處理超詳細(xì)講解

    這篇文章主要介紹了SpringBoot封裝響應(yīng)處理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • Java對(duì)象的復(fù)制三種方式(小結(jié))

    Java對(duì)象的復(fù)制三種方式(小結(jié))

    這篇文章主要介紹了Java對(duì)象的復(fù)制三種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Struts2 漏洞分析及如何提前預(yù)防

    Struts2 漏洞分析及如何提前預(yù)防

    2016年4月26日,Struts2發(fā)布一份安全公告,CVE編號(hào) CVE-2016-3081。這是自2012年Struts2命令執(zhí)行漏洞大規(guī)模爆發(fā)之后,該服務(wù)時(shí)隔四年再次爆發(fā)大規(guī)模漏洞。該漏洞也是今年目前爆出的最嚴(yán)重安全漏洞。本文分析了漏洞的原理危害影響防護(hù)等內(nèi)容。
    2016-05-05

最新評(píng)論