Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Resilience4j

Introduction to Resilience4j

2020年4月 #jsug 勉強会での資料です。Netflix Hystrixの代替となるサーキットブレイカーライブラリResilience4jおよびSpring Bootでの利用方法の解説です。

Masatoshi Tada

April 08, 2020
Tweet

More Decks by Masatoshi Tada

Other Decks in Technology

Transcript

  1. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࣗݾ঺հ ▸ ଟాਅහʢ!TVLF@NBTBʣ ▸ ݚमτϨʔφʔ!ΧαϨΞϧ ▸

    4QSJOH+BWB&&.JDSPTFSWJDFT $MPVE'PVOESZ,VCFSOFUFT ▸ 1JWPUBMೝఆߨࢣ ▸ ೔ຊ4QSJOHϢʔβձελοϑ 
  2. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ϚΠΫϩαʔϏε͸ߟ͑Δ͜ͱ͕͍ͬͺ͍  Circuit Breaker Design for

    Failure Service Discovery Distributed Tracing API Gateway Observability Polyglot Persistence Containerization Orchestration
  3. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH <౾஌ࣝ>4QSJOH$MPVEͷόʔδϣϯ ▸ ӳࠃϩϯυϯࢢ಺ͷ֗ͷ໊લ͕෇͍͍ͯΔ  Spring Cloud

    ରԠ͢ΔSpring Bootͷόʔδϣϯ Angel ??? Brixton ??? Camden ??? Dalston ??? Edgware 1.5 Finchley 2.0 Greenwich 2.1 Hoxton 2.2 ←ࠓίί
  4. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH /FUqJY044 ▸ /FUqJYࣾ͸ϚΠΫϩαʔϏεʹඞཁͳϥΠϒϥϦΛɺ ΦϦδφϧͷ044ͱͯ͠࡞͍ͬͯΔ ▸ )ZTUSJY

    αʔΩοτϒϨΠΧʔ  ▸ 3JCCPO ϩʔυόϥϯγϯά  ▸ &VSFLB αʔϏεσΟεΧόϦʔ  ▸ ;VVM "1*ήʔτ΢ΣΠ  ▸ ɾɾɾ 
  5. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVE/FUqJY ▸ 4QSJOHͱ/FUqJY044Λ࿈ܞͤ͞ΔϥΠϒϥϦ ▸ TQSJOHDMPVETUBSUFSOFUqJYIZTUSJY ▸

    TQSJOHDMPVETUBSUFSOFUqJYSJCCPO ▸ TQSJOHDMPVETUBSUFSOFUqJYFVSFLBTFSWFS ▸ TQSJOHDMPVETUBSUFSOFUqJY[VVM ▸ ɾɾɾ ▸ ਺೥લ͸4QSJOH$MPVEͷ୅໊ࢺతଘࡏͩͬͨ 
  6. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVE/FUqJY΋େ൒͕อकϞʔυ΁ ▸ TQSJOHDMPVEOFUqJYIZTUSJY ▸ TQSJOHDMPVEOFUqJYIZTUSJYDPOUSBDU ▸

    TQSJOHDMPVEOFUqJYIZTUSJYEBTICPBSE ▸ TQSJOHDMPVEOFUqJYIZTUSJYTUSFBN ▸ TQSJOHDMPVEOFUqJYSJCCPO ▸ TQSJOHDMPVEOFUqJY[VVM ▸ TQSJOHDMPVEOFUqJYUVSCJOF ▸ TQSJOHDMPVEOFUqJYUVSCJOFTUSFBN ▸ TQSJOHDMPVEOFUqJYBSDIBJVT  ˞FVSFLB͸ର৅֎ https://spring.io/blog/2019/01/23/spring-cloud-greenwich-release-is-now-available ΑΓ
  7. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVE/FUqJYͷ୅ସ ͋͘·ͰҰྫ ▸ )ZTUSJYˠ3FTJMJFODFK ▸ &VSFLBˠ4QSJOH$MPVE$POTVM

    ▸ ;VVMˠ4QSJOH$MPVE(BUFXBZ ▸ 3JCCPOˠ4QSJOH$MPVE-PBE#BMBODFS ▸ "SDIJVTˠ4QSJOH$MPVE$POpH ▸ 5VSCJOFˠ.JDSPNFUFS 1SPNFUIFVT  ※܁Γฦ͠ʹͳΓ·͕͢ɺZuulɾEureka͓Αͼspring-cloud-netflix-eurekaͷ։ൃ͸ܧଓ͍ͯ͠·͢
  8. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 3FTJMJFODFKͱ͸ ▸ )ZTUSJYʹ୅ΘΔαʔΩοτϒϨΠΧʔϥΠϒϥϦ ▸ ؔ਺ܕϓϩάϥϛϯάϞσϧ͕ಛ௃ ▸

    ࡞ऀ͸3PCFSU8JOLMFSࢯ !SCSUXOLMS  ▸ 4QSJOH΍/FUqJYͱ͸ಠཱͨ͠ϓϩδΣΫτ͕ͩ ▸ )ZTUSJYͷ3&"%.&ʹ͸ʮ୅ΘΓʹ3FTJMJFODFKΛΦεεϝ ͢ΔΑʂʯͱॻ͍ͯ͋Δ ▸ 4QSJOH#PPUͱͷ࿈ܞػೳΛఏڙ͍ͯ͠Δ 
  9. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ΞυΦϯϞδϡʔϧ ▸ 4QSJOH#PPU4UBSUFS ▸ 3FUSPpUBEBQUFS ▸

    'FJHOBEBQUFS ▸ $JSDVMBS#V⒎FS&WFOU DPOTVNFS ▸ ,PUMJODPSPVUJOFTTVQQPSU ▸ 3BUQBDL4UBSUFS ▸ 7FSUY'VUVSFEFDPSBUPS  ▸ $VTUPN3Y+BWBPQFSBUPST ▸ $VTUPN4QSJOH3FBDUPSPQFSBUPST ▸ .JDSPNFUFS.FUSJDTFYQPSUFS ▸ %SPQXJ[BSE.FUSJDTFYQPSUFS ▸ 1SPNFUIFVT.FUSJDTFYQPSUFS ▸ $BNFM$JSDVJU#SFBLFS ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS ▸ IUUQLSFTJMJFODFNPEVMF
  10. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͜Μͳίʔυ  // ઃఆͷ࡞੒ CircuitBreakerConfig config

    = CircuitBreakerConfig.ofDefaults(); // Registryͷ࡞੒ CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config); // αʔΩοτϒϨΠΧʔͷ࡞੒ CircuitBreaker cb = registry.circuitBreaker("backendB");
  11. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͜Μͳίʔυ  // όοΫΤϯυݺͼग़͠ΛσίϨʔτ Supplier<String> ds

    = cb.decorateSupplier( () -> backendBService.doSomething()); // ݺͼग़࣮͠ߦ Try<String> result = Try.ofSupplier(ds) // ྫ֎࣌ͷ୅ସॲཧ .recover(throwable -> "Recovery"); // ݁ՌΛऔಘ String resultValue = result.get();
  12. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ϚΠΫϩαʔϏε͸ͳͥ೉͍͠ʁ ▸ ো֐ͷൃੜ֬཰͕ɺϞϊϦεΑΓ֨ஈʹ্͕Δ͔Βʂ ᶃ ෼ׂ͢ΔʹؒʹωοτϫʔΫ͕ೖΔʹো֐఺͕૿͑Δ ▸

    ʮ෼ࢄίϯϐϡʔςΟϯάͷམͱ݀͠ʯͰݕࡧ ᶄ Քಇ཰͸ࢦ਺ؔ਺తʹ௿Լ͢Δ ▸ ྫʣͷ৐㲈ɺͷ৐㲈 ᶅ සൟʹσϓϩΠɾεέʔϧ͢Δʹγϟοτμ΢ϯ͕සൟ ▸ λΠϛϯάѱ͘ɺγϟοτμ΢ϯதʹϦΫΤετ͕དྷΔ͔΋ 
  13. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH %FTJHOGPS'BJMVSF ▸ ૬खͷো֐Λৗʹ૝ఆͯ͠ઃܭ͢΂͠ ▸ Ϩεϙϯε͕ฦͬͯ͜ͳ͔ͬͨΒͲ͏͠Α͏ʁ ▸

    Ϩεϙϯε͕ͱͯ΋஗͔ͬͨΒͲ͏͠Α͏ʁ ▸ εςʔλείʔυ΍σʔλߏ଄͕૝ఆ֎ͩͬͨΒ Ͳ͏͠Α͏ʁ  ϚΠΫϩ αʔϏε " ϚΠΫϩ αʔϏε #
  14. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷ໾ׂ ▸ ૬खͷো֐Λݕ஌ͨ͠ΒϦΫΤετૹ৴ΛࢭΊɺ ▸ ແବͳॲཧΛ͠ͳ͍Α͏ʹ͢Δ ▸

    ૬खʹ͜ΕҎ্ͷෛՙΛ͔͚ͳ͍Α͏͢Δ  ϚΠΫϩ αʔϏε " ϚΠΫϩ αʔϏε # ᶃϦΫΤετૹ৴ ᶄҟৗͳϨεϙϯε౳ ᶅ୅ସॲཧ ɹΛ࣮ߦ ᶆҎ߱͸ϦΫΤετૹ৴ͤͣ ɹ୅ସॲཧͷΈ࣮ߦ
  15. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷঢ়ଶ  ঢ়ଶ ϦΫΤετ ૹ৴ ୅ସॲཧ

    CLOSED (ਖ਼ৗ) ͢Δ ҟৗͳϨεϙϯε࣌ ͷΈ࣮ߦ OPEN (ҟৗ) ͠ͳ͍ ৗʹ࣮ߦ ʢ૬खʹϦΫΤετ ૹ৴͠ͳ͍ʣ HALF_OPEN (CLOSEDʹ໭Ζ͏ͱ͢Δ) ͢Δ ʢࢦఆճ਺ͷΈʣ ҟৗͳϨεϙϯε࣌ ͷΈ࣮ߦ ˞΋͏ͭಛผͳঢ়ଶ͕ଘࡏ͠·͕͢ɺࠓճ͸આ໌ͷൣғ֎ͱ͠·͢
  16. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷঢ়ଶભҠ  $-04&% 01&/ )"-'@01&/ ࣦഊ཰㱢ᮢ஋PS

    ݺग़஗Ԇ཰㱢ᮢ஋ ͋Δ࣌ؒ ͕ܦա ࣦഊ཰ʻᮢ஋BOE ݺग़஗Ԇ཰ʻᮢ஋ ࣦഊ཰㱢ᮢ஋PS ݺग़஗Ԇ཰㱢ᮢ஋
  17. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ʮࣦഊʯʮݺग़஗Ԇʯͱ͸ ▸ ࣦഊʹྫ֎ͷൃੜ ▸ ର৅ͷྫ֎͸ઃఆՄೳʢσϑΥϧτͰ͸શྫ֎͕ର৅ʣ ▸

    ݺग़஗Ԇʹ໭Γ஋͕ฦΔ·Ͱͷ͕࣌ؒᮢ஋Λ௒͑Δ ▸ ᮢ஋͸ઃఆՄೳʢσϑΥϧτ͸ඵʣ  CircuitBreaker cb = ...; Supplier<String> ds = cb.decorateSupplier( () -> backendBService.doSomething()); ྫ֎ʹࣦഊɺ஗͍ʹݺग़஗Ԇ
  18. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ճ਺ϕʔεͷεϥΠσΟϯά΢Οϯυ΢  public class FixedSizeSlidingWindowMetrics implements

    Metrics { // ॥؀഑ྻͷ௕͞ private final int windowSize; // ॥؀഑ྻͷશཁૉΛूܭͨ݁͠ՌΛอ࣋ private final TotalAggregation totalAggregation; // ݸผͷݺग़݁ՌΛอ࣋͢Δ॥؀഑ྻ private final Measurement[] measurements; // ॥؀഑ྻͷΠϯσοΫε int headIndex; ▸ /ݸͷݺग़݁Ռͷ॥؀഑ྻͰอ࣋ ▸ / ݸ໨Ҏ߱ͷݺग़݁Ռ͸ɺݹ͍݁ՌΛ্ॻ͖͢Δ
  19. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࣌ؒϕʔεͷεϥΠσΟϯά΢Οϯυ΢  public class SlidingTimeWindowMetrics implements

    Metrics { // 1ඵຖͷݺग़݁ՌूܭΛอ࣋͢Δ॥؀഑ྻ final PartialAggregation[] partialAggregations; // ॥؀഑ྻͷ௕͞ private final int timeWindowSizeInSeconds; // ॥؀഑ྻͷશཁૉΛूܭͨ݁͠ՌΛอ࣋ private final TotalAggregation totalAggregation; // ॥؀഑ྻͷΠϯσοΫε int headIndex; ▸ ֤ඵؒͷ෦෼ू໿Λ/ݸͷ॥؀഑ྻͰอ࣋ ▸ ճճͷݺग़݁Ռ͸อ࣋͠ͳ͍ ▸ / ඵ໨Ҏ߱ͷݺग़݁Ռ͸ɺݹ͍݁ՌΛ্ॻ͖͢Δ
  20. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࣦഊ཰ɺݺग़஗Ԇ཰ͷܭࢉํ๏ $-04&%ˠ01&/ ▸ ࣦഊ཰ʹ ࣦഊճ਺×૯ݺग़ճ਺ º

    ▸ ݺग़஗Ԇ཰ʹ ஗Ԇճ਺×૯ݺग़ճ਺ º ▸ ݺग़ճ਺͕࠷খݺग़ճ਺Ҏ্ʹͳͬͨΒܭࢉ͞ΕΔ ▸ ࠷খݺग़ճ਺͸ઃఆՄೳʢσϑΥϧτ͸ճʣ ▸ ٯʹݴ͏ͱɺ࠷খݺग़ճ਺ະຬͰ͸ɺશͯͷݺͼग़͕͠ ࣦഊͰ͋ͬͯ΋$-04&%͔Β01&/ʹભҠ͠ͳ͍ 
  21. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࣦഊ཰ɺݺग़஗Ԇ཰ͷܭࢉํ๏ )"-'@01&/ˠ01&/ ▸ ࠷େݺग़Մೳճ਺ͷઃఆ͕ඞཁ ▸ σϑΥϧτ͸ճɺ͜ΕΛ௒͑ͯݺͼग़͢ͱྫ֎

    ▸ ඞͣճ਺ϕʔεʹͳΔ ▸ ΢Οϯυ΢αΠζʹ࠷େݺग़Մೳճ਺ ▸ ࠷খݺग़ճ਺ʹ min(࠷େݺग़Մೳճ਺,$-04&%࣌ͷ࠷খݺग़ճ਺) 
  22. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ઃఆɿࣦഊɾݺग़஗Ԇ  ˞4QSJOH#PPUར༻࣌͸BQQMJDBUJPOQSPQFSUJFTʹઃఆՄೳͳͷͰɺ্هͷίʔυ͸ඞཁແ͠ CircuitBreakerConfig config =

    CircuitBreakerConfig.custom() .minimumNumberOfCalls(5) // ࠷খݺग़ճ਺ .failureRateThreshold(50) // ࣦഊ཰ͷᮢ஋(%) .slowCallDurationThreshold( // ݺग़஗Ԇͷᮢ஋ Duration.ofMillis(1000)) .recordExceptions( // ࣦഊͱݟͳ͢ྫ֎ͷϦετ AException.class, BException.class) .ignoreExceptions( // ࣦഊͱ΋੒ޭͱ΋͠ͳ͍ྫ֎ͷϦετ CException.class, DException.class) ... .build();
  23. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 01&/ˠ)"-'@01&/ͷ଴ͪ࣌ؒܭࢉํ๏ ▸ IntervalFunctionΠϯλϑΣʔε࣮૷Ϋϥεͷ apply()ϝιουͰࢦఆ͢Δ ▸ σϑΥϧτͰ༻ҙ͞Ε͍ͯΔ࣮૷

    ᶃ Ұఆ͚࣌ؒͩ଴ͭʢ$POTUBOU#BDLP⒎ɺσϑΥϧτʣ ᶄ ϥϯμϜͳ࣌ؒ଴ͭʢ3BOEPNJ[FE#BDLP⒎ʣ ᶅ ଴ͪ࣌ؒΛࢦ਺ؔ਺తʹ૿΍͢ʢ&YQPOFOUJBM#BDLP⒎ʣ ᶆ ϥϯμϜʴࢦ਺ؔ਺ʢ&YQPOFOUJBM3BOEPN#BDLP⒎ʣ 
  24. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ઃఆɿ01&/ˠ)"-'@01&/ͷ଴ͪ࣌ؒ  ˞4QSJOH#PPUར༻࣌͸BQQMJDBUJPOQSPQFSUJFTʹઃఆՄೳͳͷͰɺ্هͷίʔυ͸ඞཁແ͠ // Randomized Backoff

    CircuitBreakerConfig config = CircuitBreakerConfig.custom() .waitIntervalFunctionInOpenState( IntervalFunction.ofRandomized()) ... // Constant Backoff CircuitBreakerConfig config = CircuitBreakerConfig.custom() .waitDurationInOpenState(Duration.ofSeconds(3)) ...
  25. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ઃఆɿ01&/ˠ)"-'@01&/ͷ଴ͪ࣌ؒ  ˞4QSJOH#PPUར༻࣌͸BQQMJDBUJPOQSPQFSUJFTʹઃఆՄೳͳͷͰɺ্هͷίʔυ͸ඞཁແ͠ // Exponential Random

    Backoff CircuitBreakerConfig config = CircuitBreakerConfig.custom() .waitIntervalFunctionInOpenState( IntervalFunction.ofExponentialRandomBackoff( Duration.ofSeconds(1), 2)) ... // Exponential Backoff CircuitBreakerConfig config = CircuitBreakerConfig.custom() .waitIntervalFunctionInOpenState( IntervalFunction.ofExponentialBackoff( Duration.ofSeconds(1), 2)) ...
  26. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH#PPUͱͷ࿈ܞϥΠϒϥϦ ▸ SFTJMJFODFKTQSJOHCPPU ▸ 4QSJOH#PPU4UBSUFS ▸

    ผ్TQSJOHCPPUTUBSUFSBDUVBUPSͱ TQSJOHCPPUTUBSUFSBPQ΋ඞཁ ▸ SFTJMJFODFKTQSJOHDMPVE ▸ SFTJMJFODFKTQSJOHCPPUʹ 4QSJOH$MPVE$POpHͱͷ࿈ܞػೳΛՃ͑ͨ΋ͷ 
  27. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH BQQMJDBUJPOZNM  resilience4j.circuitbreaker: instances: hello-api: failure-rate-threshold:

    50 slow-call-rate-threshold: 100 slow-call-duration-threshold: 1s permitted-number-of-calls-in-half-open-state: 3 ... public HelloService(CircuitBreakerRegistry registry) { this.circuitBreaker = registry.circuitBreaker("hello-api"); } ໊લΛἧ͑Δ ໊લΛἧ͑Δ
  28. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH "VUP$POpHVSBUJPOର৅ൣғ  BQQMJDBUJPO QSPQFSUJFT CircuitBreakerConfig CircuitBreakerRegistry

    Circuit Breaker Circuit Breaker Circuit Breaker ੜ੒ ੜ੒ Πϯϓοτ #FBOఆٛࡁΈͳͷͰ ࡞੒ෆཁ
  29. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࢖͍ํ  @Service public class HelloService

    { private final CircuitBreaker circuitBreaker; // ίϯετϥΫλΠϯδΣΫγϣϯ public HelloService( CircuitBreakerRegistry registry) { this.circuitBreaker = registry.circuitBreaker("hello-api"); }
  30. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ΞϊςʔγϣϯελΠϧ  @CircuitBreaker(name = "hello-api", fallbackMethod

    = "helloFallback") public String hello() { return restTemplate.getForObject( helloApiUrl + "/hello", String.class); } // ୅ସॲཧ public String helloFallback(Throwable t) { t.printStackTrace(); return "Recover"; } ˞͜ͷ৔߹͸CircuitBreakerΠϯελϯεΛੜ੒͢Δඞཁͳ͠
  31. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͜Μͳίʔυ  import org.springframework.cloud.client.circuitbreaker.CircuitBreaker; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;

    @Service public class HelloService { private final CircuitBreaker circuitBreaker; public HelloService(..., CircuitBreakerFactory circuitBreakerFactory) { this.circuitBreaker = circuitBreakerFactory.create("hello-api"); } public String hello() { String result = circuitBreaker.run( () -> restTemplate.getForObject(helloApiUrl + "/hello", String.class), throwable -> "Recovery"); return result; } ˞@CircuitBreakerͷΑ͏ͳΞϊςʔγϣϯ͸ఏڙ͞Ε͍ͯͳ͍
  32. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH $JSDVJU#SFBLFSSVO ͷίʔυ  public class Resilience4JCircuitBreaker

    implements CircuitBreaker { @Override public <T> T run(Supplier<T> toRun, Function<Throwable, T> fallback) { // TimeLimiterΛద༻ Callable restrictedCall = TimeLimiter.decorateFutureSupplier( timeLimiter, futureSupplier); // CircuitBreakerΛద༻ Callable<T> callable = io.github.resilience4j.circuitbreaker.CircuitBreaker .decorateCallable(defaultCircuitBreaker, restrictedCall); // ࣮ߦˍϑΥʔϧόοΫॲཧ return Try.of(callable::call).recover(fallback).get(); } } ▸ $JSDVJU#SFBLFS͚ͩͰͳ͘ɺ5JNF-JNJUFS΋ ద༻͞ΕΔ
  33. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH $JSDVJU#SFBLFSɾ5JNF-JNJUFSͷઃఆ  @Bean public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer()

    { TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom() // Կ͔ΧελϚΠζ͢ΔίʔυΛॻ͘ .build(); CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() // Կ͔ΧελϚΠζ͢ΔίʔυΛॻ͘ .build(); return factory -> factory.configureDefault( ɹɹɹɹɹɹɹɹɹɹɹid -> new Resilience4JConfigBuilder(id) .timeLimiterConfig(timeLimiterConfig) .circuitBreakerConfig(circuitBreakerConfig) .build()); } ▸ $VTUPNJ[FSΛར༻͢Δ ▸ BQQMJDBUJPOQSPQFSUJFTΛ࢖͍͍ͨ৔߹ɺ ࣗ෼Ͱ$POpHVSBUJPO1SPQFSUJFTͳͲΛ࡞Δඞཁ͋Γ