æè¡çè² åµã«å¯Ÿããåãçµã¿ãšã¯ã©ãŠããã€ãã£ããªç°å¢ã§ã®ä»£è¡šçãªèšèšãã¿ãŒã³
çŸåšãŠã§ã«ã¹ããã®éçºçµç¹ã§ã¯æ¢åäºæ¥ã®æé·ãå éãããããšãæ°èŠäºæ¥ã®åãçµã¿ãé²ããããšã«äžŠè¡ããŠåãçµãã§ããŸãããããŸã§ã«ãå€§èŠæš¡ãªããŒã¿ããŒã¹ç§»è¡ãã³ã³ããåãé²ããŠããŸããããè€æ°ãµãŒãã¹ãåæäžŠè¡ã§éçºããŠããããšãããªãã§æ¹ããŠèªèãããæè¡çè² åµããã¯ã©ãŠããã€ãã£ããªã¢ãŒããã¯ãã£ãžç§»è¡ããã«ããã£ãŠæ¡çšãã代衚çãªèšèšãã¿ãŒã³ãªã©ãã玹ä»ããŸãã
ãŠã§ã«ã¹ããæ ªåŒäŒç€Ÿããã¯ãšã³ããšã³ãžãã¢ã®æµŠéãšç³ããŸãã
ãåãäžä»£ã®è±ããªèåŸã®ããã«ãæå 端ã®ãã¯ãããžãŒã掻çšããäžçæ°Žæºã®å人éèè³ç£ãã©ãããã©ãŒã ãç¯ãããããã·ã§ã³ã«æ²ããããã¢ããã€ã¶ãŒãWealthNaviãçã®ãµãŒãã¹ãæäŸããŠããŸãã
çŸåšãŠã§ã«ã¹ããã®éçºçµç¹ã§ã¯æ¢åäºæ¥ã®æé·ãå éãããããšãæ°èŠäºæ¥ã®åãçµã¿ãé²ããããšã«äžŠè¡ããŠåãçµãã§ãããŸãããããŸã§ã«ãå€§èŠæš¡ãªããŒã¿ããŒã¹ç§»è¡ãã³ã³ããåãé²ããŠããŸããããè€æ°ãµãŒãã¹ãåæäžŠè¡ã§éçºããŠããããšãããªãã§æ¹ããŠèªèãããæè¡çè² åµããã¯ã©ãŠããã€ãã£ããªã¢ãŒããã¯ãã£ãžç§»è¡ããã«ããã£ãŠæ¡çšãã代衚çãªèšèšãã¿ãŒã³ãªã©ãã玹ä»ã§ããããšæããŸãã
- æè¡çè² åµã«å¯Ÿããåãçµã¿
- ã¯ã©ãŠããã€ãã£ããªç°å¢ã§ã®ä»£è¡šçãªèšèšãã¿ãŒã³
- ãããåŠçã®èšèšãã¿ãŒã³
æè¡çè² åµã«å¯Ÿããåãçµã¿
2016幎7æã«ããã¢ããã€ã¶ãŒãWealthNaviãæ£åŒãªãªãŒã¹ããé 調ã«äºæ¥æé·ãç¶ããŠããäžã§ãã¹ããŒãéèŠã§æ©èœè¿œå ãç¹°ãè¿ããã¢ããªã·ãã¯ã¢ããªã±ãŒã·ã§ã³ãæ¥æé·ãããŠéçºã¹ããŒããèœã¡ããšããç¶æ³ã«é¥ããŸããã
å ·äœçã«ã¯ãœãŒã¹ã³ãŒãã®è¥å€§åã«äŒŽãã¢ããªã±ãŒã·ã§ã³ã®ãã«ãæéé å»¶ã人å¡å¢å ã«ããã³ãã¥ãã±ãŒã·ã§ã³ã³ã¹ãã®å¢å€§ãã¢ããªã¹ãªæ§é æ ã®å ±éåºç€ïŒæ©èœïŒã¢ããããŒãã«ãã圱é¿ç¯å²ã®æ¡å€§ã«ãšããªã確èªäœæ¥ã®çºçãªã©ã§ãã2019幎é ããéçºçµç¹ã®äžã§é¡åšåããŠãããã®ãããªèª²é¡ã»äºè±¡ã«å¯Ÿããç¶ç¶çã«è² åµã®è¿æžã«ã€ããŠè°è«ãç¶ããŠããŸãããããŒã¯ãŒãã«ãªã£ãã®ã¯ãã¹ã±ãŒã©ããªãã£ãã§ããã
è¥å€§åãããªããžããªãåå²ããŠãã«ããå¹çåãã工倫ãããããã¯ã©ãŠããã€ãã£ããªããªããªãŒãã€ãã©ã€ã³ã®æ§ç¯ãè¡ããšå ±ã«ã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ããåãé²ãããããŠããŸãããã¢ããªã¹ãªæ§é ã§ãããã³ãŒãã®éè€ãå°ãªããªãã¢ããªã±ãŒã·ã§ã³ãå°ããã€ã¯ã©ãŠããã€ãã£ããªãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ãžç§»è¡ããŠãã詊ã¿ãè¡ã£ãŠããŸãããã®ãããªè©Šã¿ãè¡ãããšã§å°ããã€ã§ããéçºçµç¹ãåãå·»ãç°å¢ã§ãã¹ã±ãŒã©ããªãã£ããåäžãã€ã€ãããŸãã
æ¬çš¿ã§ã¯ã¯ã©ãŠããã€ãã£ããªãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ãžç§»è¡ããŠããæ®µéã§æ¡çšãã2ã€ã®ä»£è¡šçãªèšèšãã¿ãŒã³ã«ã€ããŠã玹ä»ããããšæããŸãã
ã¯ã©ãŠããã€ãã£ããªç°å¢ã§ã®ä»£è¡šçãªèšèšãã¿ãŒã³
ã¯ã©ãŠããã€ãã£ããªç°å¢ã§ãããã©ããã«é¢ãããã·ã¹ãã ã¢ãŒããã¯ãã£ã®èšèšãã¿ãŒã³ã¯æããååšããŠããŸãããç¹ã«åæ£åã·ã¹ãã ã§ãããã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã§éèŠãšãããŠããèšèšãã¿ãŒã³ã®ãã¡ïŒã€ãåãäžããŸãã
ãµãŒããããã¬ãŒã«ãŒ
ãŠã§ã«ã¹ããã®ã·ã¹ãã ãæ§æããã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ãäœããã®SaaSãå©çšããŠæ©èœãå®çŸããŠããŸããSaaSãå©çšããããšãåæã®ã¢ãŒããã¯ãã£ãæšä»ã§ã¯äž»æµã«ãªã£ãŠããŸããæ±çšçãªSaaSãæ§ã ãªã¢ããªã±ãŒã·ã§ã³ããåŒã³åºããŠå©çšããŠãããããªå Žåã¯ãSaaSåŽã§é害ãèµ·ãã£ãæã®åœ±é¿ç¯å²ãåºç¯ãªãã®ã«ãªããŸãããµãŒãã¹ã®å¯çšæ§ãèé害æ§ãªã©ã®éæ©èœèŠä»¶ãããæ€èšããããã§ãã¢ãŒããã¯ãã£ãèããå¿ èŠãããã®ã§ãããŠã§ã«ã¹ããã§ã®å ·äœçãªäºäŸãšããŠãSendGridãå©çšããã¡ãŒã«éä¿¡å®è£ ã§ã¯ãããã³ã«ããã©ãŒã«ããã¯ããä»çµã¿ãåãå ¥ãããããŠããŸããããã§ã¯SaaSé害1ã«å¯ŸããŠãåãããéžæè¢ã®äžã€ãšããŠæåãªãµãŒããããã¬ãŒã«ãŒã«ã€ããŠåãäžããŸãã
å³1: ãµãŒããããã¬ãŒã«ãŒã®ã€ã¡ãŒãž
ãµãŒããããã¬ãŒã«ãŒãšã¯ç«¯çã«èª¬æãããšã倱æããå¯èœæ§ããããªã¯ãšã¹ããã¢ããªã±ãŒã·ã§ã³ãç¹°ãè¿ã詊è¡ããªãããã«ããããã®ä»ãµãŒãã¹ãžé害ãã«ã¹ã±ãŒãããªãããã«ããè£ çœ®ã®ããšãæå³ããŸãã
ãµãŒããã ãã¬ãŒã«ãŒã®å®è£ ã¯å€±æããå¯èœæ§ã®ãããªã¯ãšã¹ãã®ãããã·ãšããŠæ©èœããŸãã
ããã§ã¯resillience4jãšãããªãŒãã³ãœãŒã¹ã©ã€ãã©ãªã®å®è£ ãåæã«è©±ãé²ããŠãããŸãããµãŒããããã¬ãŒã«ãŒã¯æ¥ç¶å ã®ã·ã¹ãã ãŸãã¯ãµãŒãã¹ã®å¿çæ§ã®ç¶æ ãå ã«æéã¹ããŒããã·ã³ãä»ããŠå®è£ ãããŠããŸãã
åºå ž: https://resilience4j.readme.io/docs/circuitbreaker
å³2: ãµãŒããããã¬ãŒã«ãŒã®ç¶æ é·ç§»å³
å³2ã«ç€ºãããç¶æ ã®ä»ã«DISABLEDãšFORCED_OPENããã³METRICS_ONLYãå®è£ ãããŠããŸããããªãã·ã§ã³ãšããŠçšæãããŠããç¶æ ãªã®ã§æ¬çš¿ã§ã¯èª¬æã岿ããŸãã
ãµãŒããããã¬ãŒã«ãŒãä»ããŠæ¥ç¶ããã·ã¹ãã ãŸãã¯ãµãŒãã¹ãæ£åžžã«å¿çãè¿ãå Žåã¯CLOSEDç¶æ ã§ãã平垞æã¯åžžã«CLOSEDç¶æ ã®ã¯ãã§ããæ£åžžã§ã¯ãªãïŒç°åžžãªïŒå¿çã®è¿åŽçïŒãšã©ãŒçºççïŒãéŸå€ãè¶ ããå Žåã«ãµãŒããããã¬ãŒã«ãŒã¯OPENãžé·ç§»ããŸãããŸããOPENç¶æ ããCLOSEDç¶æ ãžæ»ãã«ã¯å¿ ãHALF_OPENç¶æ ãçµç±ããããšã«ãªããŸããHALF_OPENç¶æ ãšã¯æ¥ç¶ãããµãŒãã¹ã埩æ§ãããã©ããã確èªããã¹ããããšããŠå°ãã ããªã¯ãšã¹ãã詊ã¿ããšããç¶æ ã§ãããã®å°ãã ããšããéšåãå€ãã«ãããããããªãã®ã§ãå®è£ äŸ2ãšèšå®ãã©ã¡ãŒã¿ãŒã瀺ããªãã解説ããŠãããŸãã
resillience4jã®ãµãŒããããã¬ãŒã«ãŒå®è£ ã¯ã¢ã«ãŽãªãºã ã«Count-based sliding windowãTime-based sliding windowã®ã©ã¡ãããéžæããããšãå¯èœã§ãããã®ã¢ã«ãŽãªãºã ã®éžæã¯äž»ã«ãšã©ãŒçºççã®æ€åºæ¹æ³ã«é¢ãããŸãã
ã»ãµãŒããããã¬ãŒã«ãŒã³ã³ãã£ã°ã¬ãŒã·ã§ã³ã®å®è£ äŸ
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(Float.parseFloat("10"))
.slowCallRateThreshold(Float.parseFloat("50"))
.slowCallDurationThreshold(Duration.ofSeconds("7"))
.waitDurationInOpenState(Duration.ofMillis("1800000"))
.permittedNumberOfCallsInHalfOpenState(7)
.minimumNumberOfCalls(7)
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED)
.slidingWindowSize(30)
.recordExceptions(WebServiceException.class, XmlMappingException.class)
.build();
this.circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
Fluent Builder ãã¿ãŒã³ã§å®è£ ãããŠããCircuitBreakerConfigã¯ã©ã¹ã䜿ã£ãŠèšå®ãè¡ããŸããèšå®å®äºåŸã¬ãžã¹ããªã«ç»é²ããŸããç»é²åŸã¯InMemoryCircuitBreakerRegistryãšããã¯ã©ã¹ã§ç®¡çãããŸãã
ããããã®ãã©ã¡ãŒã¿ãŒã«ã€ããŠèŠãŠãããŸãã
| ããããã£å | ããã©ã«ãå€ | èšå®å€ïŒå®è£ äŸïŒ | 説æ |
| failureRateThreshold | 50(%) | 10(%) | ãã¬ãŒã«ãŒOPENãžé·ç§»ããéä¿¡ç°åžžå²å |
| slowCallRateThreshold | 100(%) | 50(%) | ãã¬ãŒã«ãŒOPENãžé·ç§»ããéä¿¡é å»¶å²å |
| slowCallDurationThreshold | 60000 [ms] | 7 [sec] | éä¿¡é å»¶ïŒãšå€æãããïŒæéã®éŸå€ |
| waitDurationInOpenState | 60000 [ms] | 1800000 [ms] | ãã¬ãŒã«ãŒOPENæåŸ æ©æéïŒHALF_OPENãžé·ç§»ãããŸã§ã®ã¿ã€ã ã¢ãŠãæéïŒ |
| permittedNumberOfCalls InHalfOpenState | 10 | 7 | HALF_OPENæã®åä»ãªã¯ãšã¹ãæ° |
| minimumNumberOfCalls | 100 | 7 | ãšã©ãŒçã®èšç®ã«çšããæäœãªã¯ãšã¹ãæ° |
| slidingWindowType | COUNT_BASED | TIME_BASED | ãšã©ãŒçæ€åºããžã㯠|
| slidingWindowSize | 100 | 30 | ãšã©ãŒçæ€åºãŠã£ã³ããŠãµã€ãº TIME_BASEDã®å Žåã¯ç§ãCOUNT_BASEDã®å Žåã¯ä»¶æ° |
| recordExceptions | empty | WebServiceException XmlMappingException | ãµãŒããããã¬ãŒã«ãŒã§ãšã©ãŒãšããŠèªèãããäŸå€ã¯ã©ã¹ã®ç»é² |
衚1. ãµãŒããããã¬ãŒã«ãŒã®èšå®ãªãã·ã§ã³
衚1.ã®å®è£ äŸã§ã¯ããããã£ã¯ãã¹ãŠããã©ã«ãå€ããèšå®å€ã倿ŽããŠããŸããéŸå€ããªã¯ãšã¹ãæ°ã®èšå®ã¯ãç°å¢ããµãŒãã¹ã®ç¹æ§ãSLOãªã©ãèæ ®ããäžã§æ éã«èšå®ããŠããå¿ èŠããããŸããæåããæé©å€ãèšå®ããäºã¯é£æåºŠãé«ããšæããŸãã®ã§ãéçšåã«ãã¥ãŒãã³ã°ããæéãååã«èšããããšããèŠãããŸãããã®äŸã§ã¯æ¯èŒçããã·ã§ã³ã¯ãªãã£ã«ã«ãªé åã§å©çšããæ³å®ã®ãã®ã«ãªã£ãŠããŸãããç¹åŸŽçãªéšåã¯ãšã©ãŒçæ€åºããžãã¯ïŒã¢ã«ãŽãªãºã ïŒãæéããŒã¹ã«èšå®ããŠãããšããã§ããéžæããããžãã¯ã«ãããŠã£ã³ããŠãµã€ãºã®èšå®åäœïŒç§ãŸãã¯ä»¶æ°ïŒã倿Žã«ãªãã®ã§æ³šæããŠãã ããããµãŒããããã¬ãŒã«ãŒãé 眮ããã·ã¹ãã å šäœã®ç¹æ§ã«ããã¢ã«ãŽãªãºã ãéžæããå¿ èŠããããŸããããšã³ãžãã¢ãªã³ã°ãšããŠã¯éåžžã«ããããã®ããéšåã§ãã
ã»ãµãŒããããã¬ãŒã«ãŒãå®è£ ãããµãŒãã¹åŒã³åºãã®å®è£ äŸ
try { // BackendServiceåŒã³åºã BackendServiceResponse backendServiceResponse = CircuitBreaker.decorateSupplier(circuitBreaker, () -> backendServiceClient.analyze(backendServiceRequest)).get(); return BackendServiceResponseFactory.create(backendServiceResponse); } catch (WebServiceException wse) { // äœãããã®åŠç // ... } catch (XmlMappingException xme) { // äœãããã®åŠç // ... }
CircuitBreakerã€ã³ã¿ãŒãã§ãŒã¹ãå©çšããŠããã¯ãšã³ããµãŒãã¹ãåŒã³åºããŸããbackendServiceClient.analyze() ã®å®è£ ã¯å€éšãµãŒãã¹ã«æ¥ç¶ããŠããŒã¿ãååŸããç°¡åãªWebãµãŒãã¹ã®å®è£ ãšèããŠãã ããããã®WebãµãŒãã¹ã¯WebServiceExceptionãšXmlMappingExceptionã®äŸå€ãã¹ããŒããå¯èœæ§ããããŸããèšå®ãªãã·ã§ã³ã§ãµãŒããããã¬ãŒã«ãŒã«äŸå€ãç»é²ããŠããã®ã§ãWebãµãŒãã¹åŒã³åºãã§äŸå€ãçºçããå Žåã¯ãµãŒããããã¬ãŒã«ãŒã«ãšã©ãŒãšããŠã«ãŠã³ããããŸããtry-catchã§å®è£ ããŠããŸãããVavrã䜿ã£ãŠTryã¢ããã§å®è£ ããããšãå¯èœã§ãã
CircuitBreaker.decorateSupplierã®åŒæ°ã«ã¯CircuitBreakerã®å®äœãæž¡ãå¿ èŠããããŸããSpring Bootã§ã¯ä»¥äžã®ããã«Beançææã«ã€ã³ã¹ã¿ã³ã¹åããŠãè¯ããšæããŸãã
@Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); this.circuitBreaker = this.circuitBreakerRegistry.circuitBreaker("backend-service"); this.circuitBreaker.getEventPublisher().onStateTransition(event -> { log.warn().log("CircuitBreaker of %s state transition to %s", event.getCircuitBreakerName(), event.getStateTransition().name()); }); }
ãã®äŸã§ã¯CircuitBreaderã®ã€ã³ã¹ã¿ã³ã¹åãšåæã«ããµãŒããããã¬ãŒã«ãŒã®ç¶æ é·ç§»ã€ãã³ããçºçããéã«è¡ãããåŠçïŒãã®äŸã§ã¯ãã°åºåïŒãèšå®ããŠããŸãã
resillience4jã«ã¯Spring Bootå°çšã®ã©ã€ãã©ãªãçšæãããŠããã®ã§ãSpring Bootç°å¢ã§ããã°å©çšããã®ããããããããŸããã
https://resilience4j.readme.io/docs/getting-started-3
ãµãŒããããã¬ãŒã«ãŒãšJavaã«ãããµãŒããããã¬ãŒã«ãŒå®è£ ã©ã€ãã©ãªã§ããresillience4jã䜿ã£ããµãŒãã¹åŒã³åºãã®ã玹ä»ã§ããã
ãŠã§ã«ã¹ããã®ããã¯ãšã³ããµãŒãã¹ã§ãå©çšããŠãããµãŒããããã¬ãŒã«ãŒãã¿ãŒã³ã§ããããã©ã¡ãŒã¿ãŒèšå®ã¯éçšéå§ãããŠããè€æ°åèŠçŽãã宿œããŠããŸããç¶ç¶çã«èŠçŽããå¿ èŠãªãã©ã¡ãŒã¿ãŒã§ããããµãŒããããã¬ãŒã«ãŒã®ç¶æ é·ç§»ãã¢ã©ãŒããªã©ããã°åºåãªã©ã«ããå¯èŠåã§ããŠããã®ã§ãã¥ãŒãã³ã°äœæ¥èªäœã¯ããã»ã©é£ãããããŸããã忣ã·ã¹ãã ç°å¢ã§ã¯ã·ã¹ãã éã®éä¿¡ã®ç¶æ³ãã¡ããªã¯ã¹ã®åéãå¯èŠåãªã©ã®ãªãã¶ãŒãããªãã£ãéåžžã«éèŠã§ããµãŒããããã¬ãŒã«ãŒãªã©ã®èšèšãã¿ãŒã³ãå°å ¥ããéã¯ã¢ãã¿ãªã³ã°å¯èœãªç°å¢æŽåãåãããŠè¡ãäºãæšå¥šããŸãã
â
ãªãã©ã€
ããäžã€ä»£è¡šçãªèšèšãã¿ãŒã³ã§ãããªãã©ã€ãåãäžããŸãã
åºæ¬çã«ãªãã©ã€ïŒå詊è¡ïŒã¯äžæçãªé害ã«å¯Ÿå¿ãããã®ã§ããªã¯ãšã¹ããæåããäºãåæãšããŠããŸãããã®äžæçãªé害ã¯ã»ãšãã©ã®å Žåãããã¯ãŒã¯éä¿¡ã«é¢é£ãããã®ã§ããå è¿°ãããµãŒããããã¬ãŒã«ãŒã¯å€±æããå¯èœæ§ã®ãããªã¯ãšã¹ãã®å®è¡ãæå¶ïŒåæ¢ïŒãããã®ã§ããã®ã«å¯Ÿãããªãã©ã€ã¯æåããå¯èœæ§ã®ãããªã¯ãšã¹ãã§ã®é害ã®åœ±é¿ãæå°éã«æããããšãç®çãšããŠããŸãã
宿ã«ãªãã©ã€ããã°ããããã§ã¯ãªãããªãã©ã€ã®å®æœã«ã¯ä»¥äžã®ãããªå€æãå¿ èŠã«ãªã£ãŠããŸãã
A. ç¹å®ã®äºæããããããã¯ãŒã¯ãšã©ãŒïŒå詊è¡ããïŒ
B. äžè¬çãªãããã¯ãŒã¯ãšã©ãŒïŒæéããããŠå詊è¡ããïŒ
C. èªå埩æ§ããªãæç¶çãªãšã©ãŒïŒå詊è¡ã¯ãã£ã³ã»ã«ããïŒ
Cã®å€æãç¶ç¶ããããã§ããã°ããªã¯ãšã¹ãã®å®è¡ã忢ããå¿ èŠããããããããŸããããã®å Žåã¯ãµãŒããããã¬ãŒã«ãŒãåãããŠå®è£ ãããšããã§ãããã
å³3. ãµãŒããããã¬ãŒã«ãŒãšãªãã©ã€ã®èšèšãã¿ãŒã³ãçµã¿åãããå Žåã®WebãµãŒãã¹åŒã³åºãã®å®è£ ã³ã³ããŒãã³ãã®ã¬ã€ã€ãŒã€ã¡ãŒãž
ãã€ã¯ããµãŒãã¹éçºãã¯ã©ãŠããã€ãã£ããªç°å¢ã«å¯Ÿå¿ããŠããFWãã©ã€ãã©ãªãå©çšããŠããå Žåã¯ããªãã©ã€æ©èœã¯ããããããã©ã«ãã§çšæãããŠãããšæããŸããSpringFrameworkã§ã¯RetryTemplateãçšæãããŠããããŠãŒã¶ãŒãå®çŸ©ããäŸå€çºçæã®ã¿å詊è¡ãå®è£ ããããšãç°¡æã«å®è£ ã§ããããã«ãªã£ãŠããŸãããŸããæéããããŠå詊è¡ããããå®çŸããããã®ããã¯ãªãããªã·ãŒïŒããã©ã«ãã¯NoBackOffPolicyïŒãè€æ°çšæãããŠããŸãããªãã©ã€ããªã·ãŒãæ§ã ãªãã®ãçšæãããŠãããäžã«ã¯CircuitBreakerRetryPolicyãšããå³3ã®ã€ã¡ãŒãžãå®è£ ãããã¯ã©ã¹ãååšããŸãã
ãŠã§ã«ã¹ããã®äž»èŠãªãµãŒãã¹ããã³ã¢ããªã±ãŒã·ã§ã³ã¯AWSã«ãããã€ãããŠãããæ©èœã®äžéšã¯AWSã®ãµãŒãã¹ãå©çšãã圢ã§å®çŸãããŠããŸããããã¯ãšã³ãã§ã¯AWS SDK for Javaãã€ãã£ãŠAWSã®åãµãŒãã¹ãžã¢ã¯ã»ã¹ããŠããŸããAWS SDKã®ã³ã¢ãªéšåã§è¡ãããHTTPSéä¿¡ã¯èªåãªãã©ã€ãå®è£ ãããŠãããããšã¯ã¹ããã³ã·ã£ã«ããã¯ãªãããšåŒã°ããã¢ã«ãŽãªãºã ã§å®è£ ãããŠããŸãããšã¯ã¹ããã³ã·ã£ã«ããã¯ãªãã®ä»çµã¿èªäœã¯ãããã¯ãŒã¯éä¿¡ã«é¢ããé åã§å¹ åºãå©çšãããŠãããã®ã§ããåäœã端çã«èª¬æãããšããªãã©ã€ã®éã«åŸ æ©ééãç·åœ¢ã§ã¯ãªãåŸã ã«ïŒææ°é¢æ°çã«ïŒé·ããªã£ãŠãããŸãããã®æåãçè§£ããŠãããšãããã¯ãŒã¯é害æã®ãã©ãã«ã·ã¥ãŒãã£ã³ã°ã«åœ¹ç«ã¡ãŸãã
次ã«SDKå éšã§å®éã«ã©ã®ããã«å®çŸãããŠããã®ããå°ãã玹ä»ããããšæããŸããSDKã¯ããŒãžã§ã³1.xç³»ãåæãšããŠããŸãã
S3ãžããŒã«ã«ãã¡ã€ã«ã·ã¹ãã ã«ãããã¡ã€ã«ãã¢ããããŒãããã³ãŒã
public long uploadFile(Path local, String targetS3Path, boolean shouldDeleteLocalPath) throws IOException { try (InputStream inputStream = new FileInputStream(local.toFile())) { Path s3Path = fileSystem.getPath(targetS3Path); return Files.copy(inputStream, s3Path); } finally { if (shouldDeleteLocalPath) { Files.deleteIfExists(local); } } }
S3ãžã¢ã¯ã»ã¹ããSDKãå©çšããå®è£ ã¯java.nio.file.FileSystemãæ¡åŒµããç¬èªã®ãã¡ã€ã«ã·ã¹ãã ã§ã©ãããããŠããŸããFiles.copyãåŒã³åºãããå Žåã«è¡ãããå®éã®åŠçã¯AmazonS3Client#copyObject3 ã§ããcopyObjectã¡ãœããã«æž¡ãããåŒæ°ãªã©ã¯æçµçã«AmazonS3Clientãç¶æ¿ããŠããAmazonWebServiceClientã«å®è£ ãããŠããAmazonHttpClientã®executeã¡ãœããã«åŒãæž¡ãããŠå®è¡ãããŸãããã®AmazonHttpClientã¯ã©ã¹ãSDKã®ã³ã¢ã®éšåã§ãããAWSã®åãµãŒãã¹ãžã®ãªã¯ãšã¹ããå®çŸããå®äœã§ãããã®AmazonHttpClientã«ã¯ãŠãŒã¶ãŒåŽã§æ§ã ãªãã©ã¡ãŒã¿ãŒèšå®ãã§ããããã«ãªã£ãŠãããAmazonWebServiceClientã®ClientConfigurationãå©çšããŠè¡ããŸããå°ãClientConfigurationã¯ã©ã¹ã¯ã¹ã¬ããã»ãŒãã§ã¯ãªãã®ã§æ°ãä»ããŠãã ãããæ¬é¡ã®ãªãã©ã€ããªã·ãŒã«ã€ããŠã¯ClientConfigurationã¯ã©ã¹ã«ããã©ã«ãã§å®çŸ©ãããŠããŸããClientConfigurationãæèããSDKãçŽ ã§äœ¿ã£ãŠããªãã©ã€ããªã·ãŒãé©çšãããŠããŸãã
| RetryPolicyã³ã³ã¹ãã©ã¯ã¿ã®åŒæ° | 説æ | ããã©ã«ãå®è£ |
| RetryCondition | ãªãã©ã€ãã倿ããžãã¯ã®å®è£ | SDKDefaultRetryCondition |
| BackoffStrategy | ããã¯ãªãã¢ã«ãŽãªãºã ã®æŠç¥ | SDKDefaultBackoffStrategy |
| maxErrorRetry | æå€§ãªãã©ã€åæ°ïŒæŽæ°ïŒ | 3 |
衚2. AWS SDKã®ããã©ã«ããªãã©ã€ããªã·ãŒ
RetryConditionã®ããã©ã«ãå®è£ ãèŠããšãIOExceptionãšAmazonServiceExceptionã®å Žåã®ã¿ãªãã©ã€ããããšã«ãªã£ãŠããŸããAmazonServiceExceptionã§ãã£ãŠã以äžã®å Žåã®ã¿ãªãã©ã€ãèš±å¯ããŠããŸãã
- ãªãã©ã€å¯èœãªãµãŒãã¹ã§ããããš
- ã¹ããããªã³ã°äŸå€
- ã¯ããã¯ã¹ãã¥ãŒäŸå€
BackoffStrategyã®ããã©ã«ãå®è£ ã¯ããšã¯ã¹ããã³ã·ã£ã«ããã¯ãªãã¢ã³ããžãã¿ãŒãã§ããã¹ããããªã³ã°äŸå€ãšãã以å€ã§ã¯å éšã§éžæããããžãã¿ãŒïŒä¹±æ°ïŒã®ã¢ã«ãŽãªãºã ãç°ãªããŸããã¹ããããªã³ã°äŸå€ã®å Žåã¯âEqual Jitterâã§ãã以å€ã¯âFull Jitterâã«ãªã£ãŠããŸãã詳现ãªã¢ã«ãŽãªãºã ã®èª¬æã¯AWSã®å ¬åŒããã°ã§ã確èªãã ããã
ããããã®ãã©ã¡ãŒã¿ãŒå€ã¯ããã©ã«ãã§ã¯ä»¥äžã®éãã§ããããã©ã«ãå€ã¯ClientConfigurationã䜿ã£ãŠã«ã¹ã¿ãã€ãºå¯èœã§ãã
- âFull Jitterâã®åŸ æ©æé: 100 (ms)
- âEqual Jitterâã®åŸ æ©æéâ: 500 (ms)
- æå€§ããã¯ãªãæé: 20 (sec)
AWS SDKãå©çšããå ŽåããŠãŒã¶ãŒã¯æèããªããŠããªãã©ã€ãå®è£ ãããŠããããšã«ãªãã®ã§ãå¥éãªãã©ã€ãå®è£ ããå¿ èŠã¯åºæ¬çã«ã¯ç¡ãã¯ãã§ããäžæ¹ã§SDKå éšã®åäœä»æ§ãããçè§£ããã«èª€ã£ãå©çšã®ä»æ¹ãããŠããŸããšæ³å®å€ã®æåãåŒãèµ·ããå¯èœæ§ãããã®ã§ãSDKãå©çšããå Žåã¯ããæ³šæããŠå®è£ ããããã«å¿ãããŠããŸãã
ClienctConfigurationã䜿ã£ãŠãã©ã¡ãŒã¿ãŒãã«ã¹ã¿ãã€ãºããå Žåã®å®è£ äŸã§ãã
@Component public class AmazonS3Factory implements InitializingBean { private ClientConfiguration clientConfiguration; public AmazonS3 build(AWSCredentialsProvider credentials) { return AmazonS3ClientBuilder.standard() .withCredentials(credentials) .withClientConfiguration(clientConfiguration) .build(); } @Override public void afterPropertiesSet() throws Exception { try { Resource resource = new ClassPathResource( "aws-sdk.properties"); Properties props = PropertiesLoaderUtils .loadProperties(resource); int connectionTimeout = Integer .parseInt(props.getProperty("connectionTimeout", "0")); int socketTimeout = Integer .parseInt(props.getProperty("socketTimeout", "0")); int maxConnections = Integer .parseInt(props.getProperty("maxConnections", "255")); int maxErrorRetry = Integer .parseInt(props.getProperty("maxErrorRetry", "3")); int requestTimeout = Integer .parseInt(props.getProperty("requestTimeout", "0")); int clientExecutionTimeout = Integer .parseInt(props.getProperty("clientExecutionTimeout", "0")); int baseDelay = Integer .parseInt(props.getProperty("baseDelay", "100")); int maxBackoffTime = Integer .parseInt(props.getProperty("maxBackoffTime", "20000")); clientConfiguration = new ClientConfiguration(); clientConfiguration.setConnectionTimeout(connectionTimeout); clientConfiguration.setSocketTimeout(socketTimeout); clientConfiguration.setMaxConnections(maxConnections); clientConfiguration.setMaxErrorRetry(maxErrorRetry); clientConfiguration.setRequestTimeout(requestTimeout); clientConfiguration.setClientExecutionTimeout(clientExecutionTimeout); clientConfiguration.setRetryPolicy(new RetryPolicy( PredefinedRetryPolicies.DEFAULT_RETRY_CONDITION, new PredefinedBackoffStrategies.FullJitterBackoffStrategy(baseDelay, maxBackoffTime), maxErrorRetry, true) ); } catch (Exception e) { // } } }
AWS SDKãSpringFrameworkã§ãå®è£ ãããŠãããªãã©ã€æ©èœã§ãããresilliencej4ã§ããªãã©ã€æ©èœãæäŸãããŠããŸãããããã®å®è£ ãåºæ¬çã«ã¯ãšã¯ã¹ããã³ã·ã£ã«ããã¯ãªãã¢ã«ãŽãªãºã ã§å®è£ ãæäŸãããŠããã®ã§ãç¹æ®µã®åªå£ãããããã§ã¯ãªãã䜿ãã®ç°å¢ã«åãããŠå©çšããã®ããããšæããŸãã
ã¯ã©ãŠããã€ãã£ããªç°å¢ã§ã®ãµãŒããããã¬ãŒã«ãŒãšãªãã©ã€ã®èšèšãã¿ãŒã³ã«ã€ããŠèŠãŠããŸãããããã®ã»ãã«ã代衚çãªãã®ãšããŠæµéå¶åŸ¡ïŒã¬ãŒããªããã¿ãŒïŒããã«ã¯ããããCQRSãªã©åæ£ã·ã¹ãã ã§ã¯å®çªãšãªãèšèšãã¿ãŒã³ããããŸããAWSåºç€ã§æ¡çšãããŠããã¬ãŒããªãããã®ã¢ã«ãŽãªãºã ã§ããããŒã¯ã³ãã±ããã¢ã«ãŽãªãºã ã¯éåžžã«æåã§ãããããã®èšèšãã¿ãŒã³ã¯èŠä»¶ã«å¿ããŠé©çšããŠãããã®ã§ã¯ãããŸãããèšèšãã¿ãŒã³ãå®è£ æè¡ã ãã§ã¯è§£æ±ºã§ããªãåé¡ããããŸããç¹ã«ãã€ã¯ããµãŒãã¹åãé²ããŠããäžã§æè¡é¢ã ãã§ã¯è§£æ±ºã§ããªãåé¡ãé¡åšåããŠãããšèããŠããŸãããŠã§ã«ã¹ããã§ãçµç¹æ§é ãè¥å€§åããå ±éãªããžããªãéçšäœå¶ãžã®äŸåãªã©æ§ã ãªåé¡ãæ±ãã€ã€ã âãã®ã¥ããããéèæ©é¢âã®ããžã§ã³ãæ²ã次äžä»£ã®éèã€ã³ãã©ãæ§ç¯ãã¹ãæ¥ã 奮éããŠããŸãã
â
ãããåŠçã®èšèšãã¿ãŒã³
ãŠã§ã«ã¹ããã«ã¯ãžã§ããšåŒã°ãããããåŠçãã倧ããªãã®ïŒæ³šæå·è¡ãææ°æèšç®ãªã©ïŒããå°ããªãã®ïŒãã¡ã€ã«ãã³ããŒããã ãïŒãŸã§ãã¹ãŠå«ãããšæ°çŸåãããŸãããžã§ãã®äžæ žããªããããåŠçãåãããŠããã¢ããªã±ãŒã·ã§ã³ã¯ïŒã€ãããããããäºæ¥æé·ãšãšãã«è¥å€§åããŠãããŸãããè¥å€§åããŠãããšãšãã«éçºéçšæ§ã¯äœäžããŠããŸããã
ããã§ã3幎ã»ã©åããäžå®ã®æ¥ååäœã§ãžã§ããéžå¥ããŠã³ã³ããåºç€ãžç§»è¡ããåãçµã¿ãè¡ã£ãŠããŸããã³ã³ããåºç€ã¯ECSïŒon FargateïŒã䜿ã£ãŠããŸããECSïŒon FargateïŒã®ãããšããã¯Fargateã®ãããšããã«éçŽãããã®ã§ããïŒç¬ïŒãOS管çäžèŠã§ãã€å®å šãªã³ããã³ãã§éçšã§ããéœåºŠèµ·åã®ãããåŠçã«ã¯æé©ã§ããèµ·åæéã®ãªãŒããŒããããããã®ã§ãåŠçæéã«å³ããå¶çŽãããå Žåã¯äºåèµ·åããïŒãããã¹ã¿ã³ãã€ïŒãªã©ã®å·¥å€«ãå¿ èŠã§ãããŠã§ã«ã¹ããã§ã¯ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãå ±éã§å©çšã§ãããã€ãã©ã€ã³ãæ§ç¯ããŠããã®ã§ãã³ã³ããåããã¢ããªã±ãŒã·ã§ã³ã¯ãªãªãŒã¹ãŸã§ã®å·¥çšãã¯ã€ãã¯ã«å®è¡ã§ããã¡ãªããã享åã§ããŸãããžã§ãã¯ãã¡ã€ã³ã®å¢çãæç¢ºã§ãªããžããªãç¬ç«ãããããšïŒä»ã®ã©ã€ãã©ãªããããžã§ã¯ãã«äŸåããªãïŒã«ããåŒå®³ããããªããããä»ã®ãšããéåžžã«ããæ©èœããŠããŸãã
ãŠã§ã«ã¹ããã®ãããåŠçã§äœ¿ãããŠããããŒã¿åŠçã®ãã¿ãŒã³ã®ãã¡2ã€ãåãäžããŠã¿ãããšæããŸãã
ã¹ããªããããŒãž
ã²ãšã€ãã¯ã¹ããªããïŒã¢ã³ãïŒããŒãžãšåŒã°ããèšèšãã¿ãŒã³ã§ãããŠã§ã«ã¹ããã§ã¯ãã®ãã¿ãŒã³ã䜿ã£ãŠãã¡ã€ã«åºåã®åŠçæ§èœãæ¹åããŸããã
å³4. ã¹ããªããããŒãžã®åŠçãããŒã€ã¡ãŒãž
ã¹ããªããããŒãžã®åŠçãããŒã«ã€ããŠå³3ã®é çªã«åŸã£ãŠèª¬æããŸãã
(1) ããŒã¿ããŒã¹ãããã¡ã€ã«åºåã«å¿ èŠãªããŒã¿ãæœåºããŸãã
äœè«ïŒ
äžè¬çã«åŠçæ§èœæ¹åãè¡ãå Žåã«æãæ³šç®ãããã®ã¯ã¯ãšãªã®ããã©ãŒãã³ã¹ã ãšæããŸããããŒã¿æœåºåŠçãæãåŠçã³ã¹ããé«ãå Žåã¯å°ãªããããŸãããã¯ãšãªã®ããã©ãŒãã³ã¹åäžã«ã¯ç¶ç¶çãªãã¥ãŒãã³ã°ãæ¬ ãããŸããããŠã§ã«ã¹ããã§ã¯ã¹ããŒã¯ãšãªãå¯èŠåã§ããããã«ä»çµã¿åããŠãããå®è¡æéãéŸå€ãè¶ ããå Žåã¯éããã«éçºè ãžéç¥ãè¡ãããæ¹åãè¡ã£ãŠããŸãã
(2) æœåºããããŒã¿ãåå²ããããµã€ãºïŒãã¡ã€ã«åºååŠçã®äžŠåæ°ïŒã«åå²ããŸããããã§ã¯ããŒã«ã«ã®ãã¡ã€ã«ã·ã¹ãã ãæ³å®ããŠããŸãããµãŒããŒã¬ã¹ã®ã¯ã©ãŠãç°å¢ã§ããã°ããŒã«ã«ã®ã¹ãã¬ãŒãžã«äœè£ããªãå ŽåããããšæããŸãããã®å Žåã¯ã¯ã©ãŠãã®ã¹ãã¬ãŒãžãµãŒãã¹ãªã©ãå©çšããããšãèããããŸãã
(3) ããã»ã¹å éšã§çæãããã¹ã¬ããæ¯ã«ãã¡ã€ã«åºååŠçãè¡ããŸãã
(4) ã¹ã¬ããæ¯ã«åºåããããã¡ã€ã«ãããŒãžããŠãå¿ èŠã«å¿ããŠæŽåœ¢ïŒãã©ãŒãããïŒåŠçãªã©ãè¡ããŸããããããŒãããã¿ãŒãªã©ãå¿ èŠãªå Žåã¯ããã§åŠçããŸãã
ã¹ããªããããŒãžã¯ã·ã³ãã«ã§ããã¥ã©ãŒãªåæ£ããŒã¿åŠçã®æ°Žå¹³ã¹ã±ãŒã«ãã¿ãŒã³ã§ãã忣ããŒã¿ã®åºåããã¡ã€ã«ãªã®ã§ãããŒã¿ããŒã¹è² è·ãæ¥ç¶ã³ã¹ããªã©ãæ°ã«ããå¿ èŠã¯ãããŸãããéã«å ¥ååŽããã¡ã€ã«ã§åºååŽãããŒã¿ããŒã¹ã ã£ãå Žåã¯ãããŒã¿ããŒã¹è² è·ã®åé¡ãšåãåãããšãå¿ èŠã«ãªã£ãŠããŸãã
ããŒã«ã«ãã¡ã€ã«ã·ã¹ãã ã䜿ãå Žåã¯å®è£ ãé£ãããªãã®ã§æ¯èŒçå°å ¥ãããããšããããŸãã
Javaã§ã®å®è£ äŸ
package com.example.splitmerge; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.file.FlatFileItemWriter; import org.springframework.core.io.FileSystemResource; import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; /** * ã¹ããªããããŒãžã®Javaå®è£ ãµã³ãã« */ public class SplitMergeFileTest { // åå²ãªã¹ãã®æå°åäœ private static final int MIN_CHUNK_SIZE = 1; // åºåãã¡ã€ã«ã®æåã³ãŒã private static final String FILE_CHARSET = "UTF-8"; // åºåãã¡ã€ã«ã®æ¹è¡ã³ãŒã private static final String FILE_LINE_SEPARATOR = "\n"; @Test public void execute() { // æœåºããŒã¿ãåå²ããŠãã¡ã€ã«åºåãã String artifactPath = "path/to/split_merge.csv"; List<Path> splitFiles = splitRecords2Files( artifactPath, // åºåãã¡ã€ã«ã®ãã¹ Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8"), // æœåºããŒã¿ 8 // 䞊åã¹ã¬ããæ° ); try { // åå²åºåãããã¡ã€ã«ãããŒãžãã mergeFiles(splitFiles, artifactPath); // åå²åºåãããã¡ã€ã«ãåé€ãã splitFiles.forEach(path -> { try { Files.delete(path); } catch (Exception e) { // todo } }); } catch (Exception e) { // todo } } private <T> List<Path> splitRecords2Files(String artifactPath, List<T> records, int threadCount) { List<Path> splitFiles = new ArrayList<>(); List<List<T>> partitionModels = separate(records, threadCount); ExecutorService executorService = Executors.newFixedThreadPool(threadCount); List<CompletableFuture<Path>> futures = buildFutures(artifactPath, partitionModels, executorService); CompletableFuture<Void> completableFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); completableFuture.join(); completableFuture.whenComplete((result, ex) -> { if (ex == null) { splitFiles.addAll(futures.stream().map(future -> { try { return future.get(); } catch (Exception e) { // todo } return null; }).collect(Collectors.toList())); } else { // todo } }); return splitFiles; } private <T> List<List<T>> separate(List<T> chunk, int number) { if (CollectionUtils.isEmpty(chunk) || chunk.size() <= MIN_CHUNK_SIZE) { List<List<T>> result = new ArrayList<>(); result.add(chunk); return result; } return ListUtils.partition( chunk, (chunk.size() / number) + (chunk.size() % number > 0 ? 1 : 0)); } private <T> List<CompletableFuture<Path>> buildFutures(String fileName, List<List<T>> partitionModels, ExecutorService executorService) { List<CompletableFuture<Path>> futures = new ArrayList<>(); for (int i = 0; i < partitionModels.size(); i++) { List<T> records = partitionModels.get(i); String splitFile = fileName + i; futures.add(CompletableFuture.supplyAsync(() -> outputRecords(splitFile, records), executorService)); } return futures; } private <T> Path outputRecords(String fileName, List<T> records) { FlatFileItemWriter<T> flatFileItemWriter = new FlatFileItemWriter<>(); flatFileItemWriter.setEncoding(FILE_CHARSET); flatFileItemWriter.setLineSeparator(FILE_LINE_SEPARATOR); flatFileItemWriter.setResource(new FileSystemResource(fileName)); flatFileItemWriter.setLineAggregator(item -> { // å®è£ äŸã®ããã®æ«å®å¯Ÿå¿ // todo: åãã©ã¡ãŒã¿ãŒã®å ·è±¡ã¯ã©ã¹ã«åãããŠLineAggregatorãå®è£ ããããš return (String) item; }); try { flatFileItemWriter.open(new ExecutionContext()); flatFileItemWriter.write(records); } catch (Exception e) { // todo return null; } finally { flatFileItemWriter.close(); } return Paths.get(fileName); } private void mergeFiles(List<Path> splitFiles, String artifactPath) throws Exception { Path outputFile = Paths.get(artifactPath); if (Files.exists(outputFile)) { Files.delete(outputFile); } try (OutputStream outputStream = Files.newOutputStream(outputFile, StandardOpenOption.CREATE, StandardOpenOption.APPEND)) { for (Path path : splitFiles) { List<String> lines = Files.readAllLines(path, Charset.forName(FILE_CHARSET)); IOUtils.writeLines(lines, FILE_LINE_SEPARATOR, outputStream, FILE_CHARSET); } outputStream.flush(); } catch (Exception e) { // todo } } }
â» SpringFrameworkããã³JUnitãApacheCommonsã©ã€ãã©ãªãå©çšããŠããŸãã
â
ãã¡ã³ã¢ãŠã
ãã¡ã³ã¢ãŠãïŒFan-outïŒãšããçšèªã¯é»ååè·¯ãåå°äœã®åéã§ãã䜿ãããæè¡çšèªã§ããããŸããããœãããŠã§ã¢ãšã³ãžãã¢ãªã³ã°ã®äžçã§ã䜿ãããŠããŸããããšãã°MOMïŒMessage-oriented middlewareïŒã䜿ã£ãã¡ãã»ãŒãžã³ã°åºç€ã«ãããŠãPublishãããã¡ãã»ãŒãžããã¥ãŒã€ã³ã°ãããŠè€æ°ã®Subscriberãåä¿¡ã§ããããã«ããå Žåãªã©ã«ãã¡ã³ã¢ãŠããã¿ãŒã³ãšåŒã°ãããããŸãã
å³5. SNSãšSQSã䜿ã£ããã¡ã³ã¢ãŠãã¡ãã»ãŒãžã³ã°ãã¿ãŒã³ åºå ž: https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-common-scenarios.html
ãŠã§ã«ã¹ããã§ã¯ãããåŠçã§åãæ±ãããŒã¿éãæ¥ã å¢ãç¶ããŠããŸãããã®ãããªç¶æ³åã§åé¡ã«ãªã£ãŠããã®ãåŠçæéã§ããçªç¶åŠçæéãæ¥µç«¯ã«é å»¶ãããšããäºè±¡ã¯ãŸãã§ãã»ãšãã©ã®å Žåæ°ã¥ããªãçšåºŠã®æ¥ã ã®é å»¶æéãèç©ããŠããé å»¶ç£èŠã®éŸå€ãè¶ ããŠã¢ã©ãŒããçºå ±ãããŸããããããæ¥ã ã®èгå¯ãæ ã£ãŠããããã¢ãã¿ãªã³ã°ãå®å šã§ã¯ãªãç£èŠäœå¶ã ã£ãããããšãé å»¶ã¢ã©ãŒãã¯ããæ¥çªç¶ãã£ãŠããŸããã§ãã®ã§ãåãæ±ãããŒã¿éã«é¢ãããäžå®ã®æéå ã«åŠçãå®äºãããããã®ã¢ãŒããã¯ãã£ãå¿ èŠãšãªã£ãŠããŸãã
å³6. ãã¡ã³ã¢ãŠãããããžã§ãã®ã€ã¡ãŒãž
å³5. ã¯ãã¡ã³ã¢ãŠããã¿ãŒã³ã§å®è£ ãããããããžã§ãã®ã€ã¡ãŒãžã§ããåŠçã®æµãã説æããŠãããŸãã
å è¡ã¿ã¹ã¯ïŒT1ïŒã§ã¯äºååŠçãè¡ããŸããããŒã¿ããŒã¹ããåŠçã«å¿ èŠãªããŒã¿ã®ååŸãè¡ããåŸç¶ã¿ã¹ã¯ïŒT2ïŒã®å ¥åãšãªã察象ããŒã¿ãçæãåå²ããŸããT1ã®åºåãT2ã®å ¥åã«ãªãã®ã§ãããT2ã®åŠçæéãé å»¶ç£èŠã®éŸå€ãè¶ ããªãäžå®ã®ã¹ã«ãŒããããä¿ã€ããã«T1ã®åºåã調æŽããããšãéèŠã§ããT1ã§çæãããããŒã¿ã¯ãäŸãã°ãŠãŒã¶ãŒèå¥åã®ãªã¹ãã§ããT2ã§å®å®ããŠåŠçã§ãããµã€ãºã§ãŠãŒã¶ãŒèå¥åã®ãªã¹ããåå²çæããŸããåå²ããããªã¹ãã¯åå²ãªã¹ãã¹ãã¢ã«ä¿ç®¡ãããŸãããããŸã§ãå è¡ã¿ã¹ã¯ã®åŠçã«ãªããŸããåå²ãªã¹ãã¹ãã¢ã¯AWSã䜿ãå ŽåSQSãS3ãªã©ãåè£ã«ãªããŸããSQSã®ã¡ãã»ãŒãžã®æå€§ãµã€ãºã¯256KBã§ãã®ã§ã倧ããªãµã€ãºã®åºåããŒã¿ãæ±ãå Žåã¯S3ã䜿ãããšã«ãªããŸãã
åŸç¶ã¿ã¹ã¯ã§ã¯èµ·åæã«SQSãS3ããå ¥åããŒã¿ãååŸããåŠç察象ã®ãŠãŒã¶ãŒèå¥åãç¹å®ããŸãããŠãŒã¶ãŒèå¥åã䜿ã£ãŠèªã¿ã¹ã¯ãè¡ãã¹ãåŠçãè¡ããŸããå³ã®ã€ã¡ãŒãžã§ã¯ããã»ã¹å éšã§çæãããã¹ã¬ãããã²ãšã€ã®ãŠãŒã¶ãŒèå¥åã察象ãšããŠåŠçãè¡ãããŒã¿ããŒã¹ã«ç»é²ïŒæŽæ°åŠçãè¡ã£ãŠããŸãã
T1ãT2ã®ECSã¿ã¹ã¯ã¯ãšãã«åŠçãçµäºïŒæ£åžžãç°åžžã«ãããããïŒãããShutdownããããã«å®è£ ããŠããŸããECSã¿ã¹ã¯ïŒããããžã§ãïŒã®çµäºç¶æ ã¯ãã°åºåãšdescribe-tasksãªã©ããåŸãããæ å ±ãå ã«å€å®ãè¡ããŸãã
ãªã¹ãå岿°ïŒïŒã¿ã¹ã¯äžŠåæ°ïŒã¯ãã¥ãŒãã³ã°ç®æã«ãªããŸãããŸããããŒã¿ããŒã¹ãžã®åæäžŠååŠçã¯ãããŒã¿ããŒã¹ã®è² è·ãäžæçã«é«ããå¯èœæ§ããããŸããåçŽã«ã¿ã¹ã¯ã®äžŠåæ°ãããã»ã¹å éšã®ã¹ã¬ããæ°ãå¢å ãããŠãæ³å®ã©ããã®ã¹ã«ãŒããããåŸãããªãå Žåãããã®ã§æ³šæããŠãã ãããT2ã®åºåå ãããŒã¿ããŒã¹ã®å Žåã¯ã¿ã¹ã¯ãã¹ã¬ããã®æ°Žå¹³ã¹ã±ãŒã«ïŒã¹ã±ãŒã«ã¢ãŠãïŒãšåæã«ããŒã¿ããŒã¹ã®åçŽã¹ã±ãŒã«ïŒã¹ã±ãŒã«ã¢ããïŒãå¿ èŠãªå ŽåããããŸãã
ãã®ãã¡ã³ã¢ãŠãããããžã§ãã®å®è£ ã¯T1ãšT2ã®ããããã®ã¿ã¹ã¯ã«äŸåé¢ä¿ãããã®ã§ãå®è¡æ¡ä»¶ãã¿ã¹ã¯æ°ã®å¶åŸ¡çãæè»ã«è¡ãããšãã§ããAWS StepFunctionsã䜿ãããšãèããããŸãããŠã§ã«ã¹ããã§ã¯ããŒã¿ç§»è¡ã®ã·ãã¥ãšãŒã·ã§ã³ã§ãã¡ã³ã¢ãŠããã¿ãŒã³ãæ¡çšããããšãå€ãã§ãããŸãT1ããªãT2ã®ã¿ïŒã€ãŸãECSã¿ã¹ã¯ã®äžŠåå®è¡ïŒã®ãã¿ãŒã³ã§ãããåŠçãè¡ã£ãŠãããã®ããããŸããæ³šæããŠã»ããã®ããECSã¿ã¹ã¯ã®åæå®è¡æ°ã«ã¯äžéãããããšããªãœãŒã¹ãå²ãåœãŠãããªããŠå€±æããããšãããããšã§ãããªã®ã§ECSã¿ã¹ã¯ãå©çšããããããžã§ãã®å®è£ ã§ã¯ãåå®è¡æ§ïŒãããã¯åªçæ§ïŒãèæ ®ããããšãå¿ããªãã§ãã ãããããããããã¯ããŒã¿ãåãæ±ããããªå Žåã§å€§èŠæš¡ãªäžŠåæ°ãå¿ èŠãªãžã§ããåãããŠãŒã¹ã±ãŒã¹ãªã©ã¯AWS Batchãå©çšããããšã«ãªããšæããŸãã
ãããŸã§ãããåŠçã§æ¡çšãããŠããèšèšãã¿ãŒã³ã®äžéšãã玹ä»ããŸãããã©ããªã«çŽ æŽãããèšèšãã¿ãŒã³ãå®è£ ãããšããŠãããœãããŠã§ã¢ãåãç°å¢ã¯æéãšãšãã«å€åãããã®ã§ãã®ã§ãç¶ç¶çãªæ¹åãæ ããšå€§ããªæè¡çè² åµã«ãªã£ãŠããŸããšèããŠããŸãããŸããã©ã®èšèšãã¿ãŒã³ã«ããã¬ãŒããªããååšããããšãèªèããŠããå¿ èŠããããŸãããŠã§ã«ã¹ããã®ããã¯ãšã³ãéçºããŒã ã¯æç¶å¯èœæ§ãç¶ç¶æ§ãéçšä¿å®æ§ãéåžžã«éèŠèŠããŠããŸãã
æåŸã«
ãŠã§ã«ã¹ããã§ã¯ããåãäžä»£ã«è±ãããããšããããã·ã§ã³å®çŸã®ãããããã¢ããã€ã¶ãŒãWealthNaviãã®æŽãªãæé·ãæ°èŠäºæ¥ã®éçºãªã©ãäŒç€ŸãšããŠæ°ããªå±éãè¿ããŠããŸãã
ç§ãã¡ã®ããã·ã§ã³ã«å ±é³ŽããŠãã ããæ¹ã¯ããã²äžç·ã«åããŸãããïŒ
浊é åç±ïŒKatsuyoshi UranoïŒ
ãµãŒããããã¬ãŒã«ãŒã察象ãšãããµãŒãã¹ã¯å¿ ãããSaaSã§ããå¿ èŠã¯ãããŸãããâ©
resillence4jã®ããŒãžã§ã³ã¯1.7.0ãåç §ããŠããŸããææ°ããŒãžã§ã³ãšå®è£ ã«å·®ç°ãããå¯èœæ§ãããããšããäºæ¿ãã ãããâ©
SDKãçŽ çŽã«å©çšããå Žåã®ã¢ããããŒãåŠçã¯éåžžã¯PutObjectRequestã䜿ã£ãå®è£ ã䜿ããŸãããããã§ã¯CopyObjectRequestã䜿ã£ãå®è£ ã®èª¬æãããŠããŸããâ©




