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

[SpringOne2016] Developing Microservices with Aggregates

Shin Tanimoto
September 03, 2016

[SpringOne2016] Developing Microservices with Aggregates

SpringOne Platform 2016報告会

Shin Tanimoto

September 03, 2016
Tweet

More Decks by Shin Tanimoto

Other Decks in Programming

Transcript

  1. @crichardson Developing Microservices with Aggregates Chris Richardson Founder of Eventuate.io

    Founder of the original CloudFoundry.com Author of POJOs in Action @crichardson [email protected] http://eventuate.io
  2. @crichardson Microservice architecture Browser Mobile Device Store Front UI API

    Gateway Catalog Service Review Service Order Service … Service Catalog Database Review Database Order Database … Database HTML REST REST Apply X-axis and Z-axis scaling to each service independently
  3. @crichardson Product service Customer service Order service Domain model =

    tangled web of classes Order OrderLine Item quantity … Address street city … Customer Product name price ? ? creditLimit
  4. @crichardson But it violates encapsulation… BEGIN TRANSACTION … SELECT ORDER_TOTAL

    FROM ORDERS WHERE CUSTOMER_ID = ? … SELECT CREDIT_LIMIT FROM CUSTOMERS WHERE CUSTOMER_ID = ? … INSERT INTO ORDERS … … COMMIT TRANSACTION Private to the Order Service Private to the Customer Service
  5. @crichardson 2PC is not a viable option Guarantees consistency BUT

    2PC is best avoided Not supported by many NoSQL databases etc. CAP theorem 㱺 2PC impacts availability ….
  6. @crichardson 2PC is not a viable option Guarantees consistency BUT

    2PC is best avoided Not supported by many NoSQL databases etc. CAP theorem 㱺 2PC impacts availability ….
  7. @crichardson Aggregate granularity If an update must be atomic then

    it must be handled by a single aggregate Therefore Aggregate granularity is important
  8. @crichardson Customer management How to maintain data consistency between aggregates?

    Order management Order Service placeOrder() Customer Service updateCreditLimit() Customer creditLimit ... has orders belongs to Order total Invariant: sum(open order.total) <= customer.creditLimit ?
  9. @crichardson Use event-driven, eventually consistent order processing Order Service Customer

    Service Order created Credit Reserved Credit Check Failed Create Order OR Customer creditLimit creditReservations ... Order state total … create() reserveCredit() approve()/reject()
  10. @crichardson How atomically update database and publish an event Order

    Service Order Database Message Broker insert Order publish OrderCreatedEvent dual write problem ?
  11. @crichardson Persists events  NOT current state Event table Entity

    type Event id Entity id Event data Order 902 101 … OrderApproved Order 903 101 … OrderShipped Event type Order 901 101 … OrderCreated
  12. @crichardson The present is a fold over history currentState =

    foldl(applyEvent, initialState, events)
  13. @crichardson Request handling in an event sourced application HTTP Handler

    Event Store pastEvents = findEvents(entityId) Order new() applyEvents(pastEvents) newEvents = processCmd(someCmd) saveEvents(newEvents) (optimistic locking) Order Service applyEvents(newEvents)
  14. @crichardson Event Store publishes events consumed by other services Event

    Store Event Subscriber subscribe(EventTypes) publish(event) publish(event) Customer update() Customer Service
  15. @crichardson Event Store publishes events consumed by other services Event

    Store Event Subscriber subscribe(EventTypes) publish(event) publish(event) CQRS View update() Service Xyz send notifications …
  16. @crichardson The Customer aggregate Money creditLimit Map<OrderId, Money> creditReservations Customer

    List<Event> process(CreateCustomerCommand cmd) { … } List<Event> process(ReserveCreditCommand cmd) { … } … void apply(CustomerCreatedEvent anEvent) { … } void apply(CreditReservedEvent anEvent) { … } … State Behavior
  17. @crichardson Familiar concepts restructured class Customer { public void reserveCredit(

    orderId : String, amount : Money) { // verify // update state this.xyz = … } public List<Event> process( ReserveCreditCommand cmd) { // verify … return singletonList( new CreditReservedEvent(…); ) } public void apply( CreditReservedEvent event) { // update state this.xyz = event.xyz }