国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

SpringCloud升級(jí)之路2020.0.x版-36. 驗(yàn)證斷路器正確性

NotFound / 3491人閱讀

摘要:本系列代碼地址上一節(jié)我們通過(guò)單元測(cè)試驗(yàn)證了線程隔離的正確性,這一節(jié)我們來(lái)驗(yàn)證我們斷路器的正確性,主要包括驗(yàn)證配置正確加載即我們?cè)谂渲美缰械募尤氲牡呐渲帽徽_加載應(yīng)用了。

本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent

上一節(jié)我們通過(guò)單元測(cè)試驗(yàn)證了線程隔離的正確性,這一節(jié)我們來(lái)驗(yàn)證我們斷路器的正確性,主要包括:

  1. 驗(yàn)證配置正確加載:即我們?cè)?Spring 配置(例如 application.yml)中的加入的 Resilience4j 的配置被正確加載應(yīng)用了。
  2. 驗(yàn)證斷路器是基于服務(wù)和方法打開(kāi)的,也就是某個(gè)微服務(wù)的某個(gè)方法斷路器打開(kāi)但是不會(huì)影響這個(gè)微服務(wù)的其他方法調(diào)用

驗(yàn)證配置正確加載

與之前驗(yàn)證重試類(lèi)似,我們可以定義不同的 FeignClient,之后檢查 resilience4j 加載的斷路器配置來(lái)驗(yàn)證線程隔離配置的正確加載。

并且,與重試配置不同的是,通過(guò)系列前面的源碼分析,我們知道 spring-cloud-openfeign 的 FeignClient 其實(shí)是懶加載的。所以我們實(shí)現(xiàn)的斷路器也是懶加載的,需要先調(diào)用,之后才會(huì)初始化斷路器。所以這里我們需要先進(jìn)行調(diào)用之后,再驗(yàn)證斷路器配置。

首先定義兩個(gè) FeignClient,微服務(wù)分別是 testService1 和 testService2,contextId 分別是 testService1Client 和 testService2Client

@FeignClient(name = "testService1", contextId = "testService1Client")public interface TestService1Client {    @GetMapping("/anything")    HttpBinAnythingResponse anything();}@FeignClient(name = "testService2", contextId = "testService2Client")    public interface TestService2Client {        @GetMapping("/anything")        HttpBinAnythingResponse anything();}

然后,我們?cè)黾?Spring 配置,并且給兩個(gè)微服務(wù)都添加一個(gè)實(shí)例,使用 SpringExtension 編寫(xiě)單元測(cè)試類(lèi):

//SpringExtension也包含了 Mockito 相關(guān)的 Extension,所以 @Mock 等注解也生效了@ExtendWith(SpringExtension.class)@SpringBootTest(properties = {        //默認(rèn)請(qǐng)求重試次數(shù)為 3        "resilience4j.retry.configs.default.maxAttempts=3",        // testService2Client 里面的所有方法請(qǐng)求重試次數(shù)為 2        "resilience4j.retry.configs.testService2Client.maxAttempts=2",        //默認(rèn)斷路器配置        "resilience4j.circuitbreaker.configs.default.slidingWindowSize=5",        "resilience4j.circuitbreaker.configs.default.minimumNumberOfCalls=2",        //testService2Client 的 斷路器配置        "resilience4j.circuitbreaker.configs.testService2Client.failureRateThreshold=30",        "resilience4j.circuitbreaker.configs.testService2Client.minimumNumberOfCalls=10",        })@Log4j2public class OpenFeignClientTest {    @SpringBootApplication    @Configuration    public static class App {        @Bean        public DiscoveryClient discoveryClient() {            //模擬兩個(gè)服務(wù)實(shí)例            ServiceInstance service1Instance1 = Mockito.spy(ServiceInstance.class);            ServiceInstance service2Instance2 = Mockito.spy(ServiceInstance.class);            Map zone1 = Map.ofEntries(                    Map.entry("zone", "zone1")            );            when(service1Instance1.getMetadata()).thenReturn(zone1);            when(service1Instance1.getInstanceId()).thenReturn("service1Instance1");            when(service1Instance1.getHost()).thenReturn("www.httpbin.org");            when(service1Instance1.getPort()).thenReturn(80);            when(service2Instance2.getInstanceId()).thenReturn("service1Instance2");            when(service2Instance2.getHost()).thenReturn("httpbin.org");            when(service2Instance2.getPort()).thenReturn(80);            DiscoveryClient spy = Mockito.spy(DiscoveryClient.class);            Mockito.when(spy.getInstances("testService1"))                    .thenReturn(List.of(service1Instance1));            Mockito.when(spy.getInstances("testService2"))                    .thenReturn(List.of(service2Instance2));            return spy;        }    }}

編寫(xiě)測(cè)試代碼,驗(yàn)證配置正確:

@Test    public void testConfigureCircuitBreaker() {        //防止斷路器影響        circuitBreakerRegistry.getAllCircuitBreakers().asJava().forEach(CircuitBreaker::reset);        //調(diào)用下這兩個(gè) FeignClient 確保對(duì)應(yīng)的 NamedContext 被初始化        testService1Client.anything();        testService2Client.anything();        //驗(yàn)證斷路器的實(shí)際配置,符合我們的填入的配置        List circuitBreakers = circuitBreakerRegistry.getAllCircuitBreakers().asJava();        Set collect = circuitBreakers.stream().map(CircuitBreaker::getName)                .filter(name -> {                    try {                        return name.contains(TestService1Client.class.getMethod("anything").toGenericString())                                || name.contains(TestService2Client.class.getMethod("anything").toGenericString());                    } catch (NoSuchMethodException e) {                        return false;                    }                }).collect(Collectors.toSet());        Assertions.assertEquals(collect.size(), 2);        circuitBreakers.forEach(circuitBreaker -> {            if (circuitBreaker.getName().contains(TestService1Client.class.getName())) {                Assertions.assertEquals((int) circuitBreaker.getCircuitBreakerConfig().getFailureRateThreshold(), (int) DEFAULT_FAILURE_RATE_THRESHOLD);                Assertions.assertEquals(circuitBreaker.getCircuitBreakerConfig().getMinimumNumberOfCalls(), DEFAULT_MINIMUM_NUMBER_OF_CALLS);            } else if (circuitBreaker.getName().contains(TestService2Client.class.getName())) {                Assertions.assertEquals((int) circuitBreaker.getCircuitBreakerConfig().getFailureRateThreshold(), (int) TEST_SERVICE_2_FAILURE_RATE_THRESHOLD);                Assertions.assertEquals(circuitBreaker.getCircuitBreakerConfig().getMinimumNumberOfCalls(), TEST_SERVICE_2_MINIMUM_NUMBER_OF_CALLS);            }        });    }

驗(yàn)證斷路器是基于服務(wù)和方法打開(kāi)的。

我們給 TestService1Client 添加一個(gè)方法:

@GetMapping("/status/500")String testCircuitBreakerStatus500();

這個(gè)方法一定會(huì)調(diào)用失敗,從而導(dǎo)致斷路器打開(kāi)。經(jīng)過(guò) 2 次失敗以上后(因?yàn)榕渲米钌儆|發(fā)斷路器打開(kāi)的請(qǐng)求個(gè)數(shù)為 2),驗(yàn)證斷路器狀態(tài):

@Testpublic void testCircuitBreakerOpenBasedOnServiceAndMethod() {    //防止斷路器影響    circuitBreakerRegistry.getAllCircuitBreakers().asJava().forEach(CircuitBreaker::reset);    AtomicBoolean passed = new AtomicBoolean(false);    for (int i = 0; i < 10; i++) {        //多次調(diào)用會(huì)導(dǎo)致斷路器打開(kāi)        try {            System.out.println(testService1Client.testCircuitBreakerStatus500());        } catch(Exception e) {}        List circuitBreakers = circuitBreakerRegistry.getAllCircuitBreakers().asJava();        circuitBreakers.stream().filter(circuitBreaker -> {            return circuitBreaker.getName().contains("testCircuitBreakerStatus500")                    && circuitBreaker.getName().contains("TestService1Client");        }).findFirst().ifPresent(circuitBreaker -> {            //驗(yàn)證對(duì)應(yīng)微服務(wù)和方法的斷路器被打開(kāi)            if (circuitBreaker.getState().equals(CircuitBreaker.State.OPEN)) {                passed.set(true);                //斷路器打開(kāi)后,調(diào)用其他方法,不會(huì)拋出斷路器打開(kāi)異常                testService1Client.testAnything();            }        });    }        Assertions.assertTrue(passed.get());}

這樣,我們就成功驗(yàn)證了,驗(yàn)證斷路器是基于服務(wù)和方法打開(kāi)的。

微信搜索“我的編程喵”關(guān)注公眾號(hào),每日一刷,輕松提升技術(shù),斬獲各種offer

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/123768.html

相關(guān)文章

  • SpringCloud升級(jí)之路2020.0.x-40. spock 單元測(cè)試封裝的 WebClie

    摘要:在上面打開(kāi)一個(gè)微服務(wù)某個(gè)實(shí)例的一個(gè)路徑的斷路器之后,我們調(diào)用其他的路徑,無(wú)論多少次,都成功并且調(diào)用負(fù)載均衡器獲取服務(wù)實(shí)例的次數(shù)等于調(diào)用次數(shù),代表沒(méi)有重試,也就是沒(méi)有斷路器異常。 本系列代碼地址:??https://github.com/JoJoTec/spring-cloud-parent??我們來(lái)測(cè)試下前面封裝好的 We...

    番茄西紅柿 評(píng)論0 收藏2637
  • SpringCloud升級(jí)之路2020.0.x-40. spock 單元測(cè)試封裝的 WebClie

    摘要:本系列代碼地址我們繼續(xù)上一節(jié),繼續(xù)使用測(cè)試我們自己封裝的測(cè)試針對(duì)重試測(cè)試針對(duì)重試針對(duì)響應(yīng)超時(shí),我們需要驗(yàn)證重試僅針對(duì)可以重試的方法包括方法以及配置的可重試方法,針對(duì)不可重試的方法沒(méi)有重試。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent我們繼續(xù)上一節(jié),繼續(xù)使用 spock 測(cè)試我們自己封裝的 WebClient測(cè)試針對(duì) readTi...

    番茄西紅柿 評(píng)論0 收藏2637
  • SpringCloud升級(jí)之路2020.0.x-37. 實(shí)現(xiàn)異步的客戶端封裝配置管理的意義與設(shè)計(jì)

    摘要:對(duì)于異步的請(qǐng)求,使用的是異步客戶端即。要實(shí)現(xiàn)的配置設(shè)計(jì)以及使用舉例要實(shí)現(xiàn)的配置設(shè)計(jì)以及使用舉例首先,我們要實(shí)現(xiàn)的,其包含三個(gè)重試重試的要在負(fù)載均衡之前,因?yàn)橹卦嚨臅r(shí)候,我們會(huì)從負(fù)載均衡器獲取另一個(gè)實(shí)例進(jìn)行重試,而不是在同一個(gè)實(shí)例上重試多次。 本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent 為何需要封裝異步 HT...

    fxp 評(píng)論0 收藏0
  • SpringCloud升級(jí)之路2020.0.x-41. SpringCloudGateway 基本

    摘要:將請(qǐng)求封裝成將請(qǐng)求封裝成的接口定義是但是最外層傳進(jìn)來(lái)的參數(shù)是和,需要將他們封裝成,這個(gè)工作就是在中做的。其實(shí)主要任務(wù)就是將各種參數(shù)封裝成除了和本次請(qǐng)求相關(guān)的和,還有會(huì)話管理器,編碼解碼器配置,國(guó)際化配置還有用于擴(kuò)展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來(lái),將進(jìn)入我們升級(jí)之路的又一大模塊,即網(wǎng)關(guān)模塊。網(wǎng)關(guān)模塊我們廢棄了...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • SpringCloud升級(jí)之路2020.0.x-41. SpringCloudGateway 基本

    摘要:在這里,會(huì)將上下文中載入的拼接成,然后調(diào)用其方法的,它是的處理請(qǐng)求業(yè)務(wù)的起點(diǎn)。添加相關(guān)依賴(lài)之后,會(huì)有這個(gè)。路由權(quán)重相關(guān)配置功能相關(guān)實(shí)現(xiàn)類(lèi),這個(gè)我們這里不關(guān)心。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent我們繼續(xù)分析上一節(jié)提到的 WebHandler,經(jīng)過(guò)將請(qǐng)求封裝成 ServerWebExchange 的 HttpWebHand...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<