Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Introduction to Resilience4j
Search
Masatoshi Tada
April 08, 2020
Technology
2
1.1k
Introduction to Resilience4j
2020年4月 #jsug 勉強会での資料です。Netflix Hystrixの代替となるサーキットブレイカーライブラリResilience4jおよびSpring Bootでの利用方法の解説です。
Masatoshi Tada
April 08, 2020
Tweet
Share
More Decks by Masatoshi Tada
See All by Masatoshi Tada
プロになるためのSpring上級知識 #jsug / advanced-spring-for-professionals
masatoshitada
3
2k
OpenID Connect 1.0 with Spring Security #jjug_ccc #jjug_ccc_b / oidc-with-spring-security
masatoshitada
1
1.3k
Flaskのセキュリティどうしてます?アクセス制御ライブラリCasbin入門! #pycharity / flask-authz-with-casbin
masatoshitada
0
860
今こそ知りたいSpring DI×AOP / spring-di-aop-for-every-developers
masatoshitada
4
2k
OAuth 2.0 with Spring Security #jjug_ccc #jjug_ccc_b / oauth2-with-spring-security
masatoshitada
4
1.9k
基礎から分かる!アプリケーション開発者のためのKubernetes入門 / kubernetes-basics-for-application-developers
masatoshitada
10
3.6k
2時間で分かる!Kubernetesとは何なのか / what-is-kubernetes
masatoshitada
0
930
SpringOne Platform 2019報告会 -概要、Resilience4j、LT- #jsug / springone-platform-2019
masatoshitada
0
1.2k
From Hystrix To Resilience4j
masatoshitada
1
1.1k
Other Decks in Technology
See All in Technology
「我々はどこに向かっているのか」を問い続けるための仕組みづくり / Establishing a System for Continuous Inquiry about where we are
daitasu
0
170
年間一億円削減した時系列データベースのアーキテクチャ改善~不確実性の高いプロジェクトへの挑戦~
lycorptech_jp
PRO
3
2.9k
What if...? 처음부터 다시 LLM 어플리케이션을 개발한다면
huffon
0
1k
[I/O Extended Android 2024] What`s new in Android 2024
kyeongwan
0
220
公共領域から学ぶ クラウド移行についてエンジニアが意識していること
kawakawa2222
0
140
Azure OpenAI Service Dev Day / LLMでできる!使える!生成AIエージェント
masahiro_nishimi
3
800
エンジニア向け会社紹介資料
caddi_eng
14
230k
CEL(Common Expression Language)で書いた条件にマッチしたIAM Policyを見つける / iam-policy-finder
fujiwara3
0
710
Flutter研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
160
VPoEの視点から見た、ヘンリーがサーバーサイドKotlinを使う理由 / Why Server-side Kotlin 2024
cho0o0
1
420
20240717_イケコパ代表Copilot_in_Teams会社でこう使ってます
ponponmikankan
2
430
ゆめみのアクセシビリティの現在地と今後
ryokatsuse
3
290
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
26
1.6k
A Tale of Four Properties
chriscoyier
155
22k
WebSockets: Embracing the real-time Web
robhawkes
59
7.2k
Fireside Chat
paigeccino
25
2.8k
Building Effective Engineering Teams - LeadDev
addyosmani
47
2.2k
The World Runs on Bad Software
bkeepers
PRO
63
11k
The Mythical Team-Month
searls
217
43k
Automating Front-end Workflow
addyosmani
1362
200k
Agile that works and the tools we love
rasmusluckow
325
20k
Building Your Own Lightsaber
phodgson
101
5.9k
Ruby is Unlike a Banana
tanoku
96
10k
Robots, Beer and Maslow
schacon
PRO
157
8.1k
Transcript
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH *OUSPEVDUJPOUP 3FTJMJFODFK ג ΧαϨΞϧଟాਅහ ݄ +46(ษڧձ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣗݾհ ▸ ଟాਅහʢ!TVLF@NBTBʣ ▸ ݚमτϨʔφʔ!ΧαϨΞϧ ▸
4QSJOH+BWB&&.JDSPTFSWJDFT $MPVE'PVOESZ,VCFSOFUFT ▸ 1JWPUBMೝఆߨࢣ ▸ ຊ4QSJOHϢʔβձελοϑ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 3FTJMJFODFKυΩϡϝϯτΛ༁͠·ͨ͠ʂ ▸ IUUQTHJUIVCDPNSFTJMJFODFKEPDTKB SFTJMJFODFKEPDTKB *TTVFใࠂɺϓϧϦΫͳͲ
͓͍ͪͯ͠·͢ʂ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ͜ͷηογϣϯͷత ▸ 3FTJMJFODFKυΩϡϝϯτΛಡΜͰࠔΒͳ͍Α͏ ʹɺഎܠΈΛཧղ͢Δʂ ▸ ࠓճ4QSJOH#PPUͰͷίʔυྫͳͲগͳΊ
ʢυΩϡϝϯτʹࢁ͋ΔͷͰʣ ▸ αϯϓϧίʔυ ▸ IUUQTHJUIVCDPN.BTBUPTIJ5BEBSFTJMJFODFK TQSJOHCPPUTBNQMF
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣍ ▸ 3FTJMJFODFKొͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸
4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣍ ▸ 3FTJMJFODFKొͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸
4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ϚΠΫϩαʔϏεߟ͑Δ͜ͱ͕͍ͬͺ͍ Circuit Breaker Design for
Failure Service Discovery Distributed Tracing API Gateway Observability Polyglot Persistence Containerization Orchestration
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH$MPVEͱ ▸ ϚΠΫϩαʔϏεʹඞཁͳػೳΛ·ͱΊͨ ϥΠϒϥϦ ▸ ϚΠΫϩαʔϏε։ൃΛ͋Δఔָʹͯ͘͠ΕΔ
▸ 4QSJOH#PPUϕʔε
$ $"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"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH /FUqJY044 ▸ /FUqJYࣾϚΠΫϩαʔϏεʹඞཁͳϥΠϒϥϦΛɺ ΦϦδφϧͷ044ͱͯ͠࡞͍ͬͯΔ ▸ )ZTUSJY
αʔΩοτϒϨΠΧʔ ▸ 3JCCPO ϩʔυόϥϯγϯά ▸ &VSFLB αʔϏεσΟεΧόϦʔ ▸ ;VVM "1*ήʔτΣΠ ▸ ɾɾɾ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH$MPVE/FUqJY ▸ 4QSJOHͱ/FUqJY044Λ࿈ܞͤ͞ΔϥΠϒϥϦ ▸ TQSJOHDMPVETUBSUFSOFUqJYIZTUSJY ▸
TQSJOHDMPVETUBSUFSOFUqJYSJCCPO ▸ TQSJOHDMPVETUBSUFSOFUqJYFVSFLBTFSWFS ▸ TQSJOHDMPVETUBSUFSOFUqJY[VVM ▸ ɾɾɾ ▸ લ4QSJOH$MPVEͷ໊ࢺతଘࡏͩͬͨ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH /FUqJY044ͷଟ͘อकϞʔυʹ ▸ อकϞʔυʹੵۃతʹ։ൃ͞Εͳ͍ ▸ )ZTUSJY3JCCPOอकϞʔυ ▸
&VSFLB;VVMͷ։ൃܧଓ͍ͯ͠ΔͬΆ͍ https://github.com/Netflix/Hystrix
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH0OF,FZOPUFΑΓ ▸ /FUqJYࣾ4QSJOHϓϩδΣΫτͱ ΑΓ࿈ܞ͍ͯ͘͜͠ͱΛൃද https://www.youtube.com/watch?v=mln3_o6qlBo
1:44ลΓ
$ $"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 ΑΓ
$ $"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ͷ։ൃܧଓ͍ͯ͠·͢
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 3FTJMJFODFKͱ ▸ )ZTUSJYʹΘΔαʔΩοτϒϨΠΧʔϥΠϒϥϦ ▸ ؔܕϓϩάϥϛϯάϞσϧ͕ಛ ▸
࡞ऀ3PCFSU8JOLMFSࢯ !SCSUXOLMS ▸ 4QSJOH/FUqJYͱಠཱͨ͠ϓϩδΣΫτ͕ͩ ▸ )ZTUSJYͷ3&"%.&ʹʮΘΓʹ3FTJMJFODFKΛΦεεϝ ͢ΔΑʂʯͱॻ͍ͯ͋Δ ▸ 4QSJOH#PPUͱͷ࿈ܞػೳΛఏڙ͍ͯ͠Δ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ίΞϞδϡʔϧ ▸ $JSDVJU#SFBLFSˡࠓίϨ ▸ #VMLIFBE ▸
3BUF-JNJUFS ▸ 3FUSZ ▸ $BDIF ▸ 5JNF-JNJUFS
$ $"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
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ͬ͘͟Γͱͨ͠ΞʔΩςΫνϟ CircuitBreakerConfig CircuitBreakerRegistry Circuit Breaker
Circuit Breaker Circuit Breaker ੜ ੜ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ͜Μͳίʔυ // ઃఆͷ࡞ CircuitBreakerConfig config
= CircuitBreakerConfig.ofDefaults(); // Registryͷ࡞ CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config); // αʔΩοτϒϨΠΧʔͷ࡞ CircuitBreaker cb = registry.circuitBreaker("backendB");
$ $"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();
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣍ ▸ 3FTJMJFODFKొͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸
4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ϚΠΫϩαʔϏεͳ͍ͥ͠ʁ ▸ োͷൃੜ͕֬ɺϞϊϦεΑΓ֨ஈʹ্͕Δ͔Βʂ ᶃ ׂ͢ΔʹؒʹωοτϫʔΫ͕ೖΔʹো͕૿͑Δ ▸
ʮࢄίϯϐϡʔςΟϯάͷམͱ݀͠ʯͰݕࡧ ᶄ ՔಇࢦؔతʹԼ͢Δ ▸ ྫʣͷ㲈ɺͷ㲈 ᶅ සൟʹσϓϩΠɾεέʔϧ͢Δʹγϟοτμϯ͕සൟ ▸ λΠϛϯάѱ͘ɺγϟοτμϯதʹϦΫΤετ͕དྷΔ͔
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH %FTJHOGPS'BJMVSF ▸ ૬खͷোΛৗʹఆͯ͠ઃܭ͢͠ ▸ Ϩεϙϯε͕ฦͬͯ͜ͳ͔ͬͨΒͲ͏͠Α͏ʁ ▸
Ϩεϙϯε͕ͱ͔ͯͬͨΒͲ͏͠Α͏ʁ ▸ εςʔλείʔυσʔλߏ͕ఆ֎ͩͬͨΒ Ͳ͏͠Α͏ʁ ϚΠΫϩ αʔϏε " ϚΠΫϩ αʔϏε #
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷׂ ▸ ૬खͷোΛݕͨ͠ΒϦΫΤετૹ৴ΛࢭΊɺ ▸ ແବͳॲཧΛ͠ͳ͍Α͏ʹ͢Δ ▸
૬खʹ͜ΕҎ্ͷෛՙΛ͔͚ͳ͍Α͏͢Δ ϚΠΫϩ αʔϏε " ϚΠΫϩ αʔϏε # ᶃϦΫΤετૹ৴ ᶄҟৗͳϨεϙϯε ᶅସॲཧ ɹΛ࣮ߦ ᶆҎ߱ϦΫΤετૹ৴ͤͣ ɹସॲཧͷΈ࣮ߦ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷঢ়ଶ ঢ়ଶ ϦΫΤετ ૹ৴ ସॲཧ
CLOSED (ਖ਼ৗ) ͢Δ ҟৗͳϨεϙϯε࣌ ͷΈ࣮ߦ OPEN (ҟৗ) ͠ͳ͍ ৗʹ࣮ߦ ʢ૬खʹϦΫΤετ ૹ৴͠ͳ͍ʣ HALF_OPEN (CLOSEDʹΖ͏ͱ͢Δ) ͢Δ ʢࢦఆճͷΈʣ ҟৗͳϨεϙϯε࣌ ͷΈ࣮ߦ ˞͏ͭಛผͳঢ়ଶ͕ଘࡏ͠·͕͢ɺࠓճઆ໌ͷൣғ֎ͱ͠·͢
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH αʔΩοτϒϨΠΧʔͷঢ়ଶભҠ $-04&% 01&/ )"-'@01&/ ࣦഊ㱢ᮢPS
ݺग़Ԇ㱢ᮢ ͋Δ࣌ؒ ͕ܦա ࣦഊʻᮢBOE ݺग़Ԇʻᮢ ࣦഊ㱢ᮢPS ݺग़Ԇ㱢ᮢ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ʮࣦഊʯʮݺग़Ԇʯͱ ▸ ࣦഊʹྫ֎ͷൃੜ ▸ ରͷྫ֎ઃఆՄೳʢσϑΥϧτͰશྫ֎͕ରʣ ▸
ݺग़ԆʹΓ͕ฦΔ·Ͱͷ͕࣌ؒᮢΛ͑Δ ▸ ᮢઃఆՄೳʢσϑΥϧτඵʣ CircuitBreaker cb = ...; Supplier<String> ds = cb.decorateSupplier( () -> backendBService.doSomething()); ྫ֎ʹࣦഊɺ͍ʹݺग़Ԇ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ݺग़݁Ռͷอଘ ▸ ݺग़݁ՌʢޭɺࣦഊɺԆͳͲʣ εϥΠσΟϯάΟϯυʹอଘ͞ΕΔ ▸ ճϕʔεɿ/ݸͷݺग़݁Ռͷ॥ྻͰอ࣋
ɹɹɹɹɹɹʢσϑΥϧτʣ ▸ ࣌ؒϕʔεɿ֤ඵؒͷ෦ूΛ/ݸͷ॥ྻͰอ࣋
$ $"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; ▸ /ݸͷݺग़݁Ռͷ॥ྻͰอ࣋ ▸ / ݸҎ߱ͷݺग़݁Ռɺݹ͍݁ՌΛ্ॻ͖͢Δ
$ $"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; ▸ ֤ඵؒͷ෦ूΛ/ݸͷ॥ྻͰอ࣋ ▸ ճճͷݺग़݁Ռอ࣋͠ͳ͍ ▸ / ඵҎ߱ͷݺग़݁Ռɺݹ͍݁ՌΛ্ॻ͖͢Δ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣦഊɺݺग़Ԇͷܭࢉํ๏ $-04&%ˠ01&/ ▸ ࣦഊʹ ࣦഊճ×૯ݺग़ճ º
▸ ݺग़Ԇʹ Ԇճ×૯ݺग़ճ º ▸ ݺग़ճ͕࠷খݺग़ճҎ্ʹͳͬͨΒܭࢉ͞ΕΔ ▸ ࠷খݺग़ճઃఆՄೳʢσϑΥϧτճʣ ▸ ٯʹݴ͏ͱɺ࠷খݺग़ճະຬͰɺશͯͷݺͼग़͕͠ ࣦഊͰ͋ͬͯ$-04&%͔Β01&/ʹભҠ͠ͳ͍
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣦഊɺݺग़Ԇͷܭࢉํ๏ )"-'@01&/ˠ01&/ ▸ ࠷େݺग़Մೳճͷઃఆ͕ඞཁ ▸ σϑΥϧτճɺ͜ΕΛ͑ͯݺͼग़͢ͱྫ֎
▸ ඞͣճϕʔεʹͳΔ ▸ ΟϯυαΠζʹ࠷େݺग़Մೳճ ▸ ࠷খݺग़ճʹ min(࠷େݺग़Մೳճ,$-04&%࣌ͷ࠷খݺग़ճ)
$ $"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();
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ҙ ▸ ݺग़ԆͷᮢΛઃఆͯ͠ɺ λΠϜΞτ͞ΕΔ༁Ͱͳ͍ʂʂ ▸ ྫʣᮢΛඵʹઃఆͯ͠ɺϨεϙϯεʹඵ͔͔ͬ
ͨΒͦͷॲཧඵ͔͔ΔʢඵͰଧͪΒΕͳ͍ʣ ▸ λΠϜΞτ͢ΔʹɺRestTemplateͳͲʹ λΠϜΞτઃఆ͕ඞཁ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 01&/ˠ)"-'@01&/ͷͪ࣌ؒ 01&/ )"-'@01&/ ᶃඵܦա ᶄࣦഊͨ͠߹
ɹ01&/ʹΔ ᶅ࣍Կඵͭʁ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 01&/ˠ)"-'@01&/ͷͪ࣌ؒܭࢉํ๏ ▸ IntervalFunctionΠϯλϑΣʔε࣮Ϋϥεͷ apply()ϝιουͰࢦఆ͢Δ ▸ σϑΥϧτͰ༻ҙ͞Ε͍ͯΔ࣮
ᶃ Ұఆ͚࣌ؒͩͭʢ$POTUBOU#BDLP⒎ɺσϑΥϧτʣ ᶄ ϥϯμϜͳ࣌ؒͭʢ3BOEPNJ[FE#BDLP⒎ʣ ᶅ ͪ࣌ؒΛࢦؔతʹ૿͢ʢ&YQPOFOUJBM#BDLP⒎ʣ ᶆ ϥϯμϜʴࢦؔʢ&YQPOFOUJBM3BOEPN#BDLP⒎ʣ
$ $"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)) ...
$ $"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)) ...
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ओཁͳΫϥεͷΫϥεਤ 1PXFSFECZ1MBOU6.- ˞ਖ਼֬ͳΫϥεਤͷه๏ʹͳ͍ͬͯͳ͍͔͠Εͳ͍ͷͰɺ ɹงғؾͰಡΜͰ͍͍ͩ͘͞
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣍ ▸ 3FTJMJFODFKొͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸
4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH#PPUͱͷ࿈ܞϥΠϒϥϦ ▸ SFTJMJFODFKTQSJOHCPPU ▸ 4QSJOH#PPU4UBSUFS ▸
ผ్TQSJOHCPPUTUBSUFSBDUVBUPSͱ TQSJOHCPPUTUBSUFSBPQඞཁ ▸ SFTJMJFODFKTQSJOHDMPVE ▸ SFTJMJFODFKTQSJOHCPPUʹ 4QSJOH$MPVE$POpHͱͷ࿈ܞػೳΛՃ͑ͨͷ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH$MPVEซ༻࣌ͷҙ ▸ TQSJOHDMPVEEFQFOEFODJFTΛؚΊ͍ͯͨ߹ɺ 3FTJMJFODFKͷόʔδϣϯ্ॻ͖͕ඞཁ ▸ TQSJOHDMPVEDJSDVJUCSFBLFS͕͍ͬͯΔ3FTJMJFODFKͷ
όʔδϣϯ͕ݹ͍ͨΊ ▸ ্ॻ͖͕ඞཁͳͷԼه ▸ SFTJMJFODFKDJSDVJUCSFBLFS ▸ SFTJMJFODFKUJNFMJNJUFS ▸ SFTJMJFODFKNJDSPNFUFS
$ $"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"); } ໊લΛἧ͑Δ ໊લΛἧ͑Δ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH "VUP$POpHVSBUJPOରൣғ BQQMJDBUJPO QSPQFSUJFT CircuitBreakerConfig CircuitBreakerRegistry
Circuit Breaker Circuit Breaker Circuit Breaker ੜ ੜ Πϯϓοτ #FBOఆٛࡁΈͳͷͰ ࡞ෆཁ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ͍ํ @Service public class HelloService
{ private final CircuitBreaker circuitBreaker; // ίϯετϥΫλΠϯδΣΫγϣϯ public HelloService( CircuitBreakerRegistry registry) { this.circuitBreaker = registry.circuitBreaker("hello-api"); }
$ $"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ΠϯελϯεΛੜ͢Δඞཁͳ͠
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH "DUVBUPSͰͷࢹ ▸ "DUVBUPSͰ$JSDVJU#SFBLFSͷঢ়ଶΛࢹͰ͖Δ ▸ BDUVBUPSNFUSJDTSFTJMJFODFKDJSDVJUCSFBLFS999 ▸
BDUVBUPSIFBMUI ▸ BDUVBUPSDJSDVJUCSFBLFST ▸ BDUVBUPSDJSDVJUCSFBLFSFWFOUT
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 1SPNFUIFVTར༻࣌ͷҙ ▸ SFTJMJFODFKQSPNFUIFVTͰͳ͘ɺ SFTJMJFODFKNJDSPNFUFS NJDSPNFUFSSFHJTUSZQSPNFUIFVTΛ͏
https://twitter.com/rbrtwnklr/status/1172792997026697216
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ࣍ ▸ 3FTJMJFODFKొͷഎܠ ▸ αʔΩοτϒϨΠΧʔͱঢ়ଶભҠ ▸
4QSJOH#PPUͰͷར༻ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFS
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH$MPVE$JSDVJU#SFBLFS ▸ 4QSJOH͓ಘҙͷநԽϥΠϒϥϦ ▸ ԼهͷରԠαʔΩοτϒϨΠΧʔͳΒɺ ಉ͡Α͏ʹѻ͑Δ
▸ 3FTJMJFODFK ▸ /FUqJY)ZTUSJY ▸ "MJCBCB4FOUJOFM ▸ 4QSJOH3FUSZ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH TQSJOHDMPVETUBSUFSDJSDVJUCSFBLFSSFTJMJFODFK ▸ 4QSJOH$MPVE$JSDVJU#SFBLFSͷ 3FTJMJFODFK࣮ ▸ $JSDVJU#SFBLFSͱ5JNF-JNJUFSؚ͕·Ε͍ͯΔ
▸ SFTJMJFODFKNJDSPNFUFSΛՃ͢Εɺ "DUVBUPSΤϯυϙΠϯτΛ࡞Δ͜ͱՄೳ
$ $"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ͷΑ͏ͳΞϊςʔγϣϯఏڙ͞Ε͍ͯͳ͍
$ $"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 ద༻͞ΕΔ
$ $"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ͳͲΛ࡞Δඞཁ͋Γ
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH 4QSJOH$MPVE$JSDVJU#SFBLFSΛ͏͔ʁ ▸ ҰൠʹɺϚΠΫϩαʔϏεؔ࿈ϥΠϒϥϦण໋͕͍ ˠͦΕΛݒ೦͢ΔͳΒ͏ ▸ நԽ͞Ε͍ͯΔͷͰɺ3FTJMJFODFKಛ༗ͷॲཧ
ॻ͖ͮΒ͘ͳΔ ˠͦΕ͕ݏͳΒΘͳ͍ ▸ ݺग़ʹ5JNF-JNJUFSඞͣద༻͞ΕΔ ˠͦΕ͕ݏͳΒΘͳ͍
$ $"4"3&"- *OD"MMSJHIUTSFTFSWFE ࣭5XJUUFSͰKTVH ·ͱΊ ▸ 3FTJMJFODFKɺ/FUqJY)ZTUSJYʹΘΔ ৽͍͠αʔΩοτϒϨΠΧʔϥΠϒϥϦ ▸ ঢ়ଶભҠͷΈΛཧղ͢Δ͜ͱ͕େ
▸ 4QSJOH#PPUͱͷ࿈ܞόονϦ ▸ 4QSJOH$MPVE$JSDVJU#SFBLFSͷར༻ ͓ΈͰ