Introduction to Resilience4j

Introduction to Resilience4j

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

5dbaf4015e7f249ab21b195ced8e9e46?s=128

Masatoshi Tada

April 08, 2020
Tweet

Transcript

  1. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH *OUSPEVDUJPOUP 3FTJMJFODFK ג ΧαϨΞϧଟాਅහ ೥݄೔ +46(ษڧձ

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

    4QSJOH+BWB&&.JDSPTFSWJDFT $MPVE'PVOESZ,VCFSOFUFT ▸ 1JWPUBMೝఆߨࢣ ▸ ೔ຊ4QSJOHϢʔβձελοϑ 
  3. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 3FTJMJFODFKυΩϡϝϯτΛ຋༁͠·ͨ͠ʂ ▸ IUUQTHJUIVCDPNSFTJMJFODFKEPDTKB SFTJMJFODFKEPDTKB  *TTVFใࠂɺϓϧϦΫͳͲ

    ͓଴͍ͪͯ͠·͢ʂ
  4. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͜ͷηογϣϯͷ໨త ▸ 3FTJMJFODFKυΩϡϝϯτΛಡΜͰࠔΒͳ͍Α͏ ʹɺഎܠ΍࢓૊ΈΛཧղ͢Δʂ ▸ ࠓճ͸4QSJOH#PPUͰͷίʔυྫͳͲ͸গͳΊ

    ʢυΩϡϝϯτʹ୔ࢁ͋ΔͷͰʣ ▸ αϯϓϧίʔυ ▸ IUUQTHJUIVCDPN.BTBUPTIJ5BEBSFTJMJFODFK TQSJOHCPPUTBNQMF 
  5. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ໨࣍ ▸ 3FTJMJFODFKొ৔ͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸

    4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS 
  6. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ໨࣍ ▸ 3FTJMJFODFKొ৔ͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸

    4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS 
  7. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ϚΠΫϩαʔϏε͸ߟ͑Δ͜ͱ͕͍ͬͺ͍  Circuit Breaker Design for

    Failure Service Discovery Distributed Tracing API Gateway Observability Polyglot Persistence Containerization Orchestration
  8. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVEͱ͸ ▸ ϚΠΫϩαʔϏεʹඞཁͳػೳΛ·ͱΊͨ ϥΠϒϥϦ ▸ ϚΠΫϩαʔϏε։ൃΛ͋Δఔ౓ָʹͯ͘͠ΕΔ

    ▸ 4QSJOH#PPUϕʔε 
  9. $ $"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 ←ࠓίί
  10. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH /FUqJY044 ▸ /FUqJYࣾ͸ϚΠΫϩαʔϏεʹඞཁͳϥΠϒϥϦΛɺ ΦϦδφϧͷ044ͱͯ͠࡞͍ͬͯΔ ▸ )ZTUSJY

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

    TQSJOHDMPVETUBSUFSOFUqJYSJCCPO ▸ TQSJOHDMPVETUBSUFSOFUqJYFVSFLBTFSWFS ▸ TQSJOHDMPVETUBSUFSOFUqJY[VVM ▸ ɾɾɾ ▸ ਺೥લ͸4QSJOH$MPVEͷ୅໊ࢺతଘࡏͩͬͨ 
  12. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH /FUqJY044ͷଟ͘͸อकϞʔυʹ ▸ อकϞʔυʹੵۃతʹ͸։ൃ͞Εͳ͍ ▸ )ZTUSJY΍3JCCPO͸อकϞʔυ ▸

    &VSFLB΍;VVMͷ։ൃ͸ܧଓ͍ͯ͠ΔͬΆ͍  https://github.com/Netflix/Hystrix
  13. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH0OF,FZOPUFΑΓ ▸ /FUqJYࣾ͸4QSJOHϓϩδΣΫτͱ ΑΓ࿈ܞ͍ͯ͘͜͠ͱΛൃද  https://www.youtube.com/watch?v=mln3_o6qlBo

    1:44ลΓ
  14. $ $"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 ΑΓ
  15. $ $"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ͷ։ൃ͸ܧଓ͍ͯ͠·͢
  16. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 3FTJMJFODFKͱ͸ ▸ )ZTUSJYʹ୅ΘΔαʔΩοτϒϨΠΧʔϥΠϒϥϦ ▸ ؔ਺ܕϓϩάϥϛϯάϞσϧ͕ಛ௃ ▸

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

    3BUF-JNJUFS ▸ 3FUSZ ▸ $BDIF ▸ 5JNF-JNJUFS 
  18. $ $"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
  19. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͬ͘͟Γͱͨ͠ΞʔΩςΫνϟ  CircuitBreakerConfig CircuitBreakerRegistry Circuit Breaker

    Circuit Breaker Circuit Breaker ੜ੒ ੜ੒
  20. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ͜Μͳίʔυ  // ઃఆͷ࡞੒ CircuitBreakerConfig config

    = CircuitBreakerConfig.ofDefaults(); // Registryͷ࡞੒ CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config); // αʔΩοτϒϨΠΧʔͷ࡞੒ CircuitBreaker cb = registry.circuitBreaker("backendB");
  21. $ $"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();
  22. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ໨࣍ ▸ 3FTJMJFODFKొ৔ͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸

    4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS 
  23. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ϚΠΫϩαʔϏε͸ͳͥ೉͍͠ʁ ▸ ো֐ͷൃੜ֬཰͕ɺϞϊϦεΑΓ֨ஈʹ্͕Δ͔Βʂ ᶃ ෼ׂ͢ΔʹؒʹωοτϫʔΫ͕ೖΔʹো֐఺͕૿͑Δ ▸

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

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

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

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

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

    ݺग़஗Ԇʹ໭Γ஋͕ฦΔ·Ͱͷ͕࣌ؒᮢ஋Λ௒͑Δ ▸ ᮢ஋͸ઃఆՄೳʢσϑΥϧτ͸ඵʣ  CircuitBreaker cb = ...; Supplier<String> ds = cb.decorateSupplier( () -> backendBService.doSomething()); ྫ֎ʹࣦഊɺ஗͍ʹݺग़஗Ԇ
  29. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ݺग़݁Ռͷอଘ ▸ ݺग़݁Ռʢ੒ޭɺࣦഊɺ஗ԆͳͲʣ͸ εϥΠσΟϯά΢Οϯυ΢ʹอଘ͞ΕΔ ▸ ճ਺ϕʔεɿ/ݸͷݺग़݁Ռͷ॥؀഑ྻͰอ࣋

    ɹɹɹɹɹɹʢσϑΥϧτʣ ▸ ࣌ؒϕʔεɿ֤ඵؒͷ෦෼ू໿Λ/ݸͷ॥؀഑ྻͰอ࣋ 
  30. $ $"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; ▸ /ݸͷݺग़݁Ռͷ॥؀഑ྻͰอ࣋ ▸ / ݸ໨Ҏ߱ͷݺग़݁Ռ͸ɺݹ͍݁ՌΛ্ॻ͖͢Δ
  31. $ $"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; ▸ ֤ඵؒͷ෦෼ू໿Λ/ݸͷ॥؀഑ྻͰอ࣋ ▸ ճճͷݺग़݁Ռ͸อ࣋͠ͳ͍ ▸ / ඵ໨Ҏ߱ͷݺग़݁Ռ͸ɺݹ͍݁ՌΛ্ॻ͖͢Δ
  32. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ࣦഊ཰ɺݺग़஗Ԇ཰ͷܭࢉํ๏ $-04&%ˠ01&/ ▸ ࣦഊ཰ʹ ࣦഊճ਺×૯ݺग़ճ਺ º

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

    ▸ ඞͣճ਺ϕʔεʹͳΔ ▸ ΢Οϯυ΢αΠζʹ࠷େݺग़Մೳճ਺ ▸ ࠷খݺग़ճ਺ʹ min(࠷େݺग़Մೳճ਺,$-04&%࣌ͷ࠷খݺग़ճ਺) 
  34. $ $"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();
  35. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ஫ҙ ▸ ݺग़஗Ԇͷᮢ஋Λઃఆͯ͠΋ɺ λΠϜΞ΢τ͞ΕΔ༁Ͱ͸ͳ͍ʂʂ ▸ ྫʣᮢ஋Λඵʹઃఆͯ͠΋ɺϨεϙϯεʹඵ͔͔ͬ

    ͨΒͦͷॲཧ͸ඵ͔͔ΔʢඵͰଧͪ੾ΒΕͳ͍ʣ ▸ λΠϜΞ΢τ͢Δʹ͸ɺRestTemplateͳͲʹ λΠϜΞ΢τઃఆ͕ඞཁ 
  36. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 01&/ˠ)"-'@01&/ͷ଴ͪ࣌ؒ  01&/ )"-'@01&/ ᶃඵܦա ᶄࣦഊͨ͠৔߹͸

    ɹ01&/ʹ໭Δ ᶅ࣍͸Կඵ଴ͭʁ
  37. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 01&/ˠ)"-'@01&/ͷ଴ͪ࣌ؒܭࢉํ๏ ▸ IntervalFunctionΠϯλϑΣʔε࣮૷Ϋϥεͷ apply()ϝιουͰࢦఆ͢Δ ▸ σϑΥϧτͰ༻ҙ͞Ε͍ͯΔ࣮૷

    ᶃ Ұఆ͚࣌ؒͩ଴ͭʢ$POTUBOU#BDLP⒎ɺσϑΥϧτʣ ᶄ ϥϯμϜͳ࣌ؒ଴ͭʢ3BOEPNJ[FE#BDLP⒎ʣ ᶅ ଴ͪ࣌ؒΛࢦ਺ؔ਺తʹ૿΍͢ʢ&YQPOFOUJBM#BDLP⒎ʣ ᶆ ϥϯμϜʴࢦ਺ؔ਺ʢ&YQPOFOUJBM3BOEPN#BDLP⒎ʣ 
  38. $ $"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)) ...
  39. $ $"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)) ...
  40. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH  ओཁͳΫϥεͷΫϥεਤ 1PXFSFECZ1MBOU6.- ˞ਖ਼֬ͳΫϥεਤͷه๏ʹͳ͍ͬͯͳ͍͔΋͠Εͳ͍ͷͰɺ ɹงғؾͰಡΜͰ͍͍ͩ͘͞

  41. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ໨࣍ ▸ 3FTJMJFODFKొ৔ͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸

    4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS 
  42. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH#PPUͱͷ࿈ܞϥΠϒϥϦ ▸ SFTJMJFODFKTQSJOHCPPU ▸ 4QSJOH#PPU4UBSUFS ▸

    ผ్TQSJOHCPPUTUBSUFSBDUVBUPSͱ TQSJOHCPPUTUBSUFSBPQ΋ඞཁ ▸ SFTJMJFODFKTQSJOHDMPVE ▸ SFTJMJFODFKTQSJOHCPPUʹ 4QSJOH$MPVE$POpHͱͷ࿈ܞػೳΛՃ͑ͨ΋ͷ 
  43. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVEซ༻࣌ͷ஫ҙ ▸ TQSJOHDMPVEEFQFOEFODJFTΛؚΊ͍ͯͨ৔߹ɺ 3FTJMJFODFKͷόʔδϣϯ্ॻ͖͕ඞཁ ▸ TQSJOHDMPVEDJSDVJUCSFBLFS͕࢖͍ͬͯΔ3FTJMJFODFKͷ

    όʔδϣϯ͕ݹ͍ͨΊ ▸ ্ॻ͖͕ඞཁͳͷ͸Լه఺ ▸ SFTJMJFODFKDJSDVJUCSFBLFS ▸ SFTJMJFODFKUJNFMJNJUFS ▸ SFTJMJFODFKNJDSPNFUFS 
  44. $ $"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"); } ໊લΛἧ͑Δ ໊લΛἧ͑Δ
  45. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH "VUP$POpHVSBUJPOର৅ൣғ  BQQMJDBUJPO QSPQFSUJFT CircuitBreakerConfig CircuitBreakerRegistry

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

    { private final CircuitBreaker circuitBreaker; // ίϯετϥΫλΠϯδΣΫγϣϯ public HelloService( CircuitBreakerRegistry registry) { this.circuitBreaker = registry.circuitBreaker("hello-api"); }
  47. $ $"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ΠϯελϯεΛੜ੒͢Δඞཁͳ͠
  48. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH "DUVBUPSͰͷ؂ࢹ ▸ "DUVBUPSͰ$JSDVJU#SFBLFSͷঢ়ଶΛ؂ࢹͰ͖Δ ▸ BDUVBUPSNFUSJDTSFTJMJFODFKDJSDVJUCSFBLFS999 ▸

    BDUVBUPSIFBMUI ▸ BDUVBUPSDJSDVJUCSFBLFST ▸ BDUVBUPSDJSDVJUCSFBLFSFWFOUT 
  49. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 1SPNFUIFVTར༻࣌ͷ஫ҙ఺ ▸ SFTJMJFODFKQSPNFUIFVTͰ͸ͳ͘ɺ SFTJMJFODFKNJDSPNFUFS  NJDSPNFUFSSFHJTUSZQSPNFUIFVTΛ࢖͏

     https://twitter.com/rbrtwnklr/status/1172792997026697216
  50. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ໨࣍ ▸ 3FTJMJFODFKొ৔ͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸

    4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS 
  51. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVE$JSDVJU#SFBLFS ▸ 4QSJOH͓ಘҙͷந৅ԽϥΠϒϥϦ ▸ ԼهͷରԠαʔΩοτϒϨΠΧʔͳΒɺ ಉ͡Α͏ʹѻ͑Δ

    ▸ 3FTJMJFODFK ▸ /FUqJY)ZTUSJY ▸ "MJCBCB4FOUJOFM ▸ 4QSJOH3FUSZ 
  52. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH TQSJOHDMPVETUBSUFSDJSDVJUCSFBLFSSFTJMJFODFK ▸ 4QSJOH$MPVE$JSDVJU#SFBLFSͷ 3FTJMJFODFK࣮૷ ▸ $JSDVJU#SFBLFSͱ5JNF-JNJUFSؚ͕·Ε͍ͯΔ

    ▸ SFTJMJFODFKNJDSPNFUFSΛ௥Ճ͢Ε͹ɺ "DUVBUPSΤϯυϙΠϯτΛ࡞Δ͜ͱ΋Մೳ 
  53. $ $"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ͷΑ͏ͳΞϊςʔγϣϯ͸ఏڙ͞Ε͍ͯͳ͍
  54. $ $"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΋ ద༻͞ΕΔ
  55. $ $"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ͳͲΛ࡞Δඞཁ͋Γ
  56. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH 4QSJOH$MPVE$JSDVJU#SFBLFSΛ࢖͏͔ʁ ▸ ҰൠʹɺϚΠΫϩαʔϏεؔ࿈ϥΠϒϥϦ͸ण໋͕୹͍ ˠͦΕΛݒ೦͢ΔͳΒ࢖͏ ▸ ந৅Խ͞Ε͍ͯΔͷͰɺ3FTJMJFODFKಛ༗ͷॲཧ͸

    ॻ͖ͮΒ͘ͳΔ ˠͦΕ͕ݏͳΒ࢖Θͳ͍ ▸ ݺग़ʹ5JNF-JNJUFS΋ඞͣద༻͞ΕΔ ˠͦΕ͕ݏͳΒ࢖Θͳ͍ 
  57. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭໰͸5XJUUFSͰKTVH ·ͱΊ ▸ 3FTJMJFODFK͸ɺ/FUqJY)ZTUSJYʹ୅ΘΔ ৽͍͠αʔΩοτϒϨΠΧʔϥΠϒϥϦ ▸ ঢ়ଶભҠͷ࢓૊ΈΛཧղ͢Δ͜ͱ͕େ੾

    ▸ 4QSJOH#PPUͱͷ࿈ܞ΋όονϦ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFSͷར༻͸ ͓޷ΈͰ