Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

이벤트 기반 분산 시스템을 향한 여정

5,726 views

Published on

배민찬(https://www.baeminchan.com) 서비스의 백엔드 시스템 중 일부가 지난 1년간 어떤 고민과 아이디어, 결과물을 만들어냈는지 공유하려고 합니다. 발표 중 언급되는 용어나 도구에 대해 일반적인 정의나 간단한 설명은 언급되나 자세히 다루지 않습니다. 사용된 도구들로 어떻게 이벤트 기반 분산 시스템을 만들었는지에 대한 이야기가 중심입니다.

Published in: Software
  • Sex in your area for one night is there tinyurl.com/hotsexinarea Copy and paste link in your browser to visit a site)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Girls for sex are waiting for you https://bit.ly/2TQ8UAY
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Meetings for sex in your area are there: https://bit.ly/2TQ8UAY
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Best site for flirting and sex in your area you can find there: https://bit.ly/2SlcOnO
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Time to make new friends or just a simple dating is there: https://bit.ly/2FMNP6e
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

이벤트 기반 분산 시스템을 향한 여정

  1. 1. ORDER SYSTEMUSER SERVICE API GW PRODUCT SYSTEM SCM SYSTEM EXTERNAL SYSTEMS 
 MDM SYSTEMBACK-OFFICE SCM SYSTEM
 

  2. 2. SERVICE SERVICE SERVICE SERVICE SYSTEM  
  3. 3. ✔ ✔ (customizing) ✔ , 5 ✔ (Amazon Web Service)
  4. 4. LOGISTICS SYSTEM
  5. 5. LOGISTICS SYSTEM LOGISTICS ADAPTER ✔ Spring Boot (Java 1.8) ✔ AWS Elastic Beanstalk : https://allegro.tech/2015/01/working-with-legacy-architecture.html
  6. 6. LOGISTICS SYSTEM LOGISTICS ADAPTER
  7. 7. LOGISTICS SYSTEM LOGISTICS ADAPTER
  8. 8. LOGISTICS SYSTEM LOGISTICS ADAPTER • 기능 변경 또는 추가 시 많은 비용이 필요 • 코드 변경시 다양한 부수효과(side effect) 발생
  9. 9. LOGISTICS SYSTEM LOGISTICS ADAPTER
  10. 10. LOGISTICS SYSTEM LOGISTICS ADAPTER
  11. 11. . !"" build.gradle #"" src !"" config !"" main $   !"" java $   $   #"" com $   $      #"" woowahan $   $      #"" scm $   $      !"" purchase $   $         !"" domain $   $         !"" application $   $         #"" infrastructure $   $      !"" delivery $   $      #"" adapter $   $         !"" order $   $         !"" masterdata $   $         #"" logistics $   #"" resources #"" test
  12. 12. LOGISTICS SYSTEM LOGISTICS ADAPTER ✔ 부족한 비즈니스 지식과 도메인 이해도를 가지고 바로 시작할 수 있다. ✔ 필요하다면 빠르게 고칠 수 있고, 모델을 성장 시킬 수 있다. ✔ 잘 구성된 모듈은 단일 JVM에서 동작하는 마이크로서비스로 볼 수도 있다.
  13. 13. ✔ ✔ ✔ IDE LOGISTICS ADAPTER DeliveryService ----------------------
 +createInvoice(Order) PurchaseService ----------------------
 +createOrder(Order) WarehousingManagement -------------------------
 +process(OrderComplated) void process(OrderCompleted orderCompleted) { PurchaseOrder order = purchaseService.createOrder(..); logisticsOperations.register(order); DeliveryInvoice invoice = deliveryService.createInvoice(..); logisticsOperations.register(invoice); }
  14. 14. ✔ ✔ ✔ IDE @Transactional LOGISTICS ADAPTER DeliveryService ----------------------
 +createInvoice(Order) PurchaseService ----------------------
 +createOrder(Order) WarehousingManagement -------------------------
 +process(OrderComplated)
  15. 15. ✔ ✔ ✔ IDE LOGISTICS ADAPTER DeliveryService ----------------------
 +createInvoice(Order) PurchaseService ----------------------
 +createOrder(Order) WarehousingManagement -------------------------
 +process(OrderComplated)
  16. 16. LOGISTICS ADAPTER ✔ 새로운 기능을 추가하기 위해 기존 코드를 수정해야 함 ✔ 모듈간 상호 참조 등으로 순환 의존성이 생기는 등에 부작용 ✔ 즉, 모듈간 강결합으로 단일 모듈에 경계가 무너지는 현상 DeliveryService ----------------------
 +createInvoice(Order) PurchaseService ----------------------
 +createOrder(Order) WarehousingManagement -------------------------
 +process(OrderComplated) InventoryService ----------------------
 +adjustStock(Order)
  17. 17. DeliveryService PurchaseService InventoryService Warehousing Management
  18. 18. DeliveryService PurchaseService InventoryService Warehousing Management interface ApplicationEventPublisher { void publishEvent(ApplicationEvent event); void publishEvent(Object event); } class ApplicationComponent { @EventListener void handle(OrderCompleted orderCompleted) { } } interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); }
  19. 19. DeliveryService PurchaseService class InventoryService { @EventListener void handle(OrderCompleted orderCompleted) { } } class OrderEventRelayer { @SqsListener("order-message-queue") void relayEvent(OrderCompletedMessage message) { applicationEventPublisher.publishEvent( message.toOrderCompleted() ); } }
  20. 20. LOGISTICS SYSTEM LOGISTICS ADAPTER
  21. 21. RPC Stub RPC Server SHARED LIBRARY
  22. 22. HTTP Client HTTP Server - (RESOURCE) - URI - (Verb) - HTTP Method - (Representations)
  23. 23. Messaging API Messaging API MESSAGING SYSTEM
  24. 24. PRODUCT SYSTEM ORDER SYSTEM REMOTE SYSTEMS RESTFUL API
 SERVICE ORDER ADAPTER EXTERNAL ADAPTERS MESSAGING SYSTEM LOGISTICS SERVICE DELIVERY SERVICE PURCHASE SERVICE
  25. 25. PRODUCT SYSTEM ORDER SYSTEM REMOTE SYSTEMS RESTFUL API
 SERVICE ORDER ADAPTER EXTERNAL ADAPTERS MESSAGING SYSTEM LOGISTICS SERVICE DELIVERY SERVICE PURCHASE SERVICE
  26. 26. RESTFUL API
 SERVICE ORDER ADAPTER EXTERNAL ADAPTERS MESSAGING SYSTEM LOGISTICS SERVICE DELIVERY SERVICE PURCHASE SERVICE 1) 최소한의 운영 비용으로 사용 할 수 있는가? 2) 메시지 전달 신뢰성을 가지고 있는가? 3) 단일 메시지가 여러 소비자에게 전달될 수 있는가? 4) 수평 확장성을 가지고 있는가? 5) 사용하기 쉬운가? 6) 모니터링 할 수 있는가?
  27. 27. ✔ 최소 1회 이상 메시지 전달 보장, 최대 14일 유지 ✔ 무제한 확장 가능, 빠른 읽기 처리량 ✔ 메시지 풀링 방식, 단일 소비자(경쟁 소비자) ✔ 메시지 순서를 보장하지 않음 ✔ 최대 256KB 데이터 전달 ✔ AWS SDK 기반 쉬운 API 제공 1) 최소한의 운영 비용으로 사용 할 수 있는가? 2) 메시지 전달 신뢰성을 가지고 있는가? 3) 단일 메시지가 여러 소비자에게 전달될 수 있는가? 4) 수평 확장성을 가지고 있는가? 5) 사용하기 쉬운가? 6) 모니터링 할 수 있는가?
  28. 28. 1) 최소한의 운영 비용으로 사용 할 수 있는가? 2) 메시지 전달 신뢰성을 가지고 있는가? 3) 단일 메시지가 여러 소비자에게 전달될 수 있는가? 4) 수평 확장성을 가지고 있는가? 5) 사용하기 쉬운가? 6) 모니터링 할 수 있는가? ✔ 발행/구독 모델 지원(1:1, 1:n) ✔ 무제한 확장 가능 ✔ 소비자 유형별 메시지 전달 보장 ✔ 메시지 전달 보장을 위해 SQS 사용 권장 ✔ 그외 소비자 유형에 대해서는 보장 못함 ✔ AWS SDK 기반 쉬운 API 제공
  29. 29. 1) 최소한의 운영 비용으로 사용 할 수 있는가? 2) 메시지 전달 신뢰성을 가지고 있는가? 3) 단일 메시지가 여러 소비자에게 전달될 수 있는가? 4) 수평 확장성을 가지고 있는가? 5) 사용하기 쉬운가? 6) 모니터링 할 수 있는가? ✔ 메시지 전달 및 순서를 보장 ✔ 이벤트 스트리밍 지원(중복 이벤트 제어 필요) ✔ 샤드(Shard) 개념을 통해 무제한 확장 가능 ✔ 자동화된 확장이 아닌, 수동 제어 ✔ 3개 리전에 복제, 최대 7시간 동안 데이터 유지 ✔ 초당 5회 읽기 제한(샤드 당) ✔ 최대 1MB 데이터 전달
  30. 30. 1) 최소한의 운영 비용으로 사용 할 수 있는가? 2) 메시지 전달 신뢰성을 가지고 있는가? 3) 단일 메시지가 여러 소비자에게 전달될 수 있는가? 4) 수평 확장성을 가지고 있는가? 5) 사용하기 쉬운가? 6) 모니터링 할 수 있는가? ✔ 메시지 전달 및 순서를 보장 ✔ 점대점, 발행/구독 방식 메시지 기능 지원 ✔ 인스턴스 기반 확장 가능 ✔ 높은 가용성 및 메시지 안정성 ✔ 업계 표준 API 및 프로토콜 호환 ✔ AMQP, MQTT, OpenWire, STOMP 지원 ✔ JMS(Java Message Service) 지원
  31. 31. PUBLISHER SUBSCRIBER
 #1 SNS TOPIC SQS #1 SQS #2 SQS #3 SUBSCRIBER
 #2 SUBSCRIBER
 #3
  32. 32. SENDER RECEIVERSQS RECEIVER
  33. 33. PUBLISHER AWS LAMBDA SNS HTTP ENDPOINT SQS
  34. 34. PRODUCT SYSTEM ORDER SYSTEM REMOTE SYSTEMS RESTFUL API
 SERVICE ORDER ADAPTER EXTERNAL ADAPTERS SNS LOGISTICS SERVICE DELIVERY SERVICE PURCHASE SERVICE SQS SQS
  35. 35. ORDER ADAPTER EXTERNAL ADAPTERS SCM
 SNS SERVICE SERVICE SERVICE SERVICE ORDER
 SERVICE ORDER
 SNS SERVICE SQS SQS ORDER SYSTEM SCM SYSTEM SQS
  36. 36. ORDER
 SYSTEM SCM SYSTEM class OrderCompletedEvent { private Order source; private Date occurredOn; public Order getSource() { .. } public void setSource(Order source) { .. } // getter, setter } { "source" : { "id" : "2018042129392759283",
 "buyer": {},
 "deliveryAddress": {}, "orderLines" : [] }, "occurredOn" : 1520393282506 }
  37. 37. - Message - MessageChannel
 - MessageConverter - MessageHandler
  38. 38. @SqsListener("scm-adapter-order-event-queue") void handle(OrderCompletedEvent event) { // } MessageSendingOperations operations = new NotificationMessagingTemplate(amazonSNS); operations.convertAndSend("order-event-stream", OrderCompletedEvent.of(order); ORDER
 SYSTEM SCM SYSTEM
  39. 39. @StreamListener(target = Sink.INPUT, condition = "payload.eventType == 'OrderCompletedEvent'") public void handle(@Payload OrderCompletedEvent event) { // handle event } @StreamListener(target=Sink.INPUT, condition="payload.eventType == 'OrderCanceledEvent'") public void handle(@Payload OrderCanceledEvent event) { // handle event } ORDER
 SYSTEM SCM SYSTEM
  40. 40. ORDER
 SYSTEM SCM SYSTEM eventMessagePublisher.publishEvent(domainEvent); @EventListener void handle(DomainEvent event) { }
  41. 41. /
  42. 42. /
  43. 43. / {
  44. 44. Spring Messaging Woowahan Messaging AWS Woowahan Messaging Spring Cloud AWS
  45. 45. interface DomainEventPublisher { void publishEvent(DomainEvent event); } interface DomainEventSubscriber { void onEvent(DomainEvent event); }
  46. 46. interface DomainEventPublisher { void publishEvent(DomainEvent event); } class AmazonSNSDomainEventPublisher implements DomainEventPublisher { private final NotificationMessagingTemplate messagingTemplate; private final String destinationName; @Override public void publishEvent(DomainEvent event) { Map<String, Object> headers = new HashMap<>(); { headers.put(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE); } EventEnvelope<DomainEvent> payload = new EventEnvelope<>(event); messagingTemplate.convertAndSend(destinationName, payload, headers); } }
  47. 47. interface DomainEventSubscriber { void onEvent(DomainEvent event); } class AmazonSQSDomainEventSubscriber implements DomainEventSubscriber { private ApplicationEventPublisher applicationEventPublisher; private ObjectMapper objectMapper; @SqsListener("scm-adapter-order-event-queue") public void receive(@NotificationMessage JsonNode payload) { EventEnvelope eventEnvelope = objectMapper.treeToValue(payload, EventEnvelope.class); if (DomainEvent.class.isAssignableFrom(eventEnvelope.getEvent().getClass())) { onEvent((DomainEvent) eventEnvelope.getEvent()); } } @Override public void onEvent(DomainEvent event) { applicationEventPublisher.publishEvent(event); } } @EventListener void handle(OrderCompletedEvent event) { }
  48. 48. class OrderCompletedEvent { private Order source; private Date occurredOn; public Order getSource() { .. } public void setSource(Order source) { .. } // getter, setter } { "source" : { "id" : "2018042129392759283", "orderLines" : [] }, "occurredOn" : 1520393282506 } class OrderCompletedEvent { private Order source; private Date occurredOn; public Order getSource() { .. } public void setSource(Order source) { .. } // getter, setter }
  49. 49. { "event" : { "@eventType" : "woowabros.order.domain.event.OrderCompletedEvent", "source" : { "id" : "2018042129392759283", "orderLines" : [] }, "occurredOn" : 1520393282506 } } ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enableDefaultTyping(); OrderCompletedEvent event = OrderCompletedEvent.of(Order.createTemporaryOrder()); EventEnvelope envelope = EventEnvelope.wrap(event); String orderCompletedEventJSON = objectMapper.writeValueAsString(envelope); JavaType javaType = objectMapper.constructType(EventEnvelope.class); EventEnvelope envelope = objectMapper.readValue(orderCompletedEventJSON, javaType); OrderCompletedEvent event = (OrderCompletedEvent) envelope.getEvent();
  50. 50. ✔ ✔ ✔ , (EIP ) ✔ CQRS ✔ , ✔ ✔ ✔ Event Sourcing, etc ✔ ✔ ✔ (SQS) ✔ Amazon Kinesis
  51. 51. EXTERNAL SYSTEMS PRODUCT SYSTEM ORDER SYSTEM EVENT STREAM
  52. 52. ORDER SYSTEMUSER SERVICE API GW PRODUCT SYSTEM SCM SYSTEM EXTERNAL SYSTEMS 
 MDM SYSTEMBACK-OFFICE SCM SYSTEM
  53. 53. ORDER SYSTEMUSER SERVICE API GW PRODUCT SYSTEM SCM SYSTEM EXTERNAL SYSTEMS 
 MDM SYSTEMBACK-OFFICE SCM SYSTEM
  54. 54. ✔ , (Implementing Domain-Driven Design) ✔ , (Domain-Driven Design Distilled) ✔ , 5.0 2/e(Spring 5.0 Microservices - Second Edition)

×