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

When Microservices Meet Event Sourcing

When Microservices Meet Event Sourcing

Presented at:
* ThoughtWorks Tech Talks NYC Meetup on May 2017
* Developer Week Conference NYC on Jun 2017

Vinicius Gomes

May 11, 2017
Tweet

More Decks by Vinicius Gomes

Other Decks in Programming

Transcript

  1. WHEN
    MICROSERVICES
    MEET
    EVENT SOURCING
    Vinicius Gomes
    1

    View full-size slide

  2. VINICIUS GOMES
    Software developer at ThoughtWorks
    vvgomes.com/blog
    twitter.com/vvgomes
    2

    View full-size slide

  3. AGENDA
    The Traditional Approach
    Introduction to Event Sourcing
    CQRS
    Demo
    Summary
    3

    View full-size slide

  4. THE TRADITIONAL
    APPROACH
    4

    View full-size slide

  5. EXAMPLE
    Online Restaurant
    5

    View full-size slide

  6. ONLINE RESTAURANT
    Data Model
    6

    View full-size slide

  7. ONLINE RESTAURANT
    Services
    7

    View full-size slide

  8. Restaurant
    ONLINE RESTAURANT
    8
    POST
    GET
    I want to
    open an order!
    200 ✔

    View full-size slide

  9. Restaurant
    ONLINE RESTAURANT
    9
    POST
    GET
    I want to
    add an item to
    my order!
    200 ✔

    View full-size slide

  10. THE TRADITIONAL APPROACH
    • Simple to implement
    • Technology agnostic
    10
    GET
    POST
    PUT
    DELETE

    View full-size slide

  11. CHALLENGES
    11

    View full-size slide

  12. CHALLENGES
    Coupling
    12

    View full-size slide

  13. CHALLENGES
    Coupling
    Resilience
    13
    Restaurant
    POST
    GET
    I want to add an item
    to my order!
    503

    View full-size slide

  14. CHALLENGES
    Coupling
    Resilience
    Response time
    14

    View full-size slide

  15. CHALLENGES
    Coupling
    Resilience
    Response time
    User intent
    15
    POST /orders/8659a0d6/items/
    Add item to order

    View full-size slide

  16. CHALLENGES
    Coupling
    Resilience
    Response time
    User intent
    Current / mutable state
    16
    {
    "id": “6a208c41…”,
    "status": "OPEN",
    "items": [
    {
    "id": “be596c8e…”,
    "quantity": 1
    },
    {
    "id": “5d09509c…”,
    "quantity": 2
    },
    {
    "id": “cc52d1b6…”,
    "quantity": 1
    }
    ]
    }

    View full-size slide

  17. EVENT SOURCING
    17

    View full-size slide

  18. EVENT SOURCING
    18

    View full-size slide

  19. DOMAIN EVENTS
    19
    {
    "payload": {
    "orderId": “be596c8e…”,
    "itemId": “5d09509c…”,
    "quantity": 1
    },
    "payloadType": “com.restaurant.ItemAddedToOrderEvent”,
    "timestamp": “2017-03-25 08:48:51 -03:00”,
    "revision": “2”,
    "aggregateId": “6a208c41…”
    }
    Model the past
    Immutable
    Permanent

    View full-size slide

  20. EVENT STORE
    Append only
    Sequential
    Long-lived
    20

    View full-size slide

  21. AGGREGATES
    21
    state = reduce(handle, {}, events)
    Reducer function
    Reducing events into state

    View full-size slide

  22. AGGREGATES
    Example
    22
    { }

    View full-size slide

  23. AGGREGATES
    Example
    23
    payload: {
    id: “42”
    }
    {
    "id": “42”,
    "status": "OPEN",
    "items": [ ]
    }

    View full-size slide

  24. AGGREGATES
    Example
    24
    {
    "id": “42”,
    "status": "OPEN",
    "items": [
    {
    "id": “43”,
    “quantity": 1
    }
    ]
    }
    payload: {
    orderId: “42”,
    itemId: “43”,
    quantity: 1
    }

    View full-size slide

  25. payload: {
    orderId: “42”,
    itemId: “44”,
    quantity: 2
    }
    AGGREGATES
    Example
    25
    {
    "id": “42”,
    "status": "OPEN",
    "items": [
    {
    "id": “43”,
    “quantity": 1
    },
    {
    "id": “44”,
    “quantity": 2
    }
    ]
    }

    View full-size slide

  26. AGGREGATES
    Example
    26
    {
    "id": “42”,
    "status": "OPEN",
    "items": [
    {
    "id": “44”,
    “quantity": 2
    }
    ]
    }
    payload: {
    orderId: “42”,
    itemId: “43”
    }

    View full-size slide

  27. AGGREGATES
    Example
    27
    {
    "id": “42”,
    "status": "PLACED",
    "items": [
    {
    "id": “44”,
    “quantity": 2
    }
    ]
    }
    payload: {
    orderId: “42”
    }

    View full-size slide

  28. AGGREGATES
    Example
    28
    {
    "id": “42”,
    "status": "PLACED",
    "items": [
    {
    "id": “44”,
    “quantity": 2
    }
    ]
    }
    Order Aggregate

    View full-size slide

  29. COMMANDS
    29
    Add item to order
    {
    "type": “com.restaurant.AddItemToOrderCommand”,
    "payload": {
    "orderId": “be596c8e…”,
    "itemId": “5d09509c…”,
    "quantity": 1
    },
    "timestamp": “2017-03-25 08:48:51 -03:00”
    }

    View full-size slide

  30. COMMANDS
    30
    (state, command) -> [event]
    Handling a command

    View full-size slide

  31. COMMANDS
    31
    How do clients send commands?

    I want to add an item
    to my order!
    ?

    View full-size slide

  32. COMMANDS
    32
    Reviewing REST
    Resource Collection
    host/api/orders

    View full-size slide

  33. COMMANDS
    33
    Reviewing REST
    Resource
    host/api/orders/8659a0d6

    View full-size slide

  34. COMMANDS
    34
    Reviewing REST
    Nested Resource
    host/api/orders/8659a0d6/items/5d1a8457

    View full-size slide

  35. COMMANDS
    35
    Reviewing REST
    HTTP Methods
    GET
    POST
    PUT/PATCH
    DELETE

    View full-size slide

  36. COMMANDS
    36
    Reviewing REST
    Hypermedia Formats

    View full-size slide

  37. COMMANDS
    37
    Commands can be resources

    View full-size slide

  38. COMMANDS
    Option #1
    Generic “Commands” nested-resource
    38
    POST /orders/8659a0d6/commands
    {
    “type": “AddItemToOrderCommand”,
    "menuItem": “/menu/items/8d30d99“,
    “quantity": 2
    }

    View full-size slide

  39. COMMANDS
    Option #2
    Command URI
    39
    POST /orders/8659a0d6/items/commands/add
    {
    "menuItem": “/menu/items/8d30d99“,
    “quantity": 2
    }

    View full-size slide

  40. COMMANDS
    Command discoverability
    40

    View full-size slide

  41. EVENT SOURCING
    41

    View full-size slide

  42. QUERIES
    Bad news
    The Event Store is not good for queries
    43
    Most applications
    •A few writes
    •A lot of reads

    View full-size slide

  43. CQRS
    Command
    Query
    Responsibility
    Segregation
    45
    Write ✍
    Read

    View full-size slide

  44. Service
    CQRS
    46

    Command
    Query
    Publish
    Listen

    View full-size slide

  45. Service A
    CQRS
    47
    Service B

    View full-size slide

  46. CQRS
    48
    Command model
    •Command definitions
    •Event definitions
    •The aggregate
    •Aggregate repository
    •Write only API
    Query model
    •Event listeners
    •Query entities
    •Repositories
    •Read only API

    View full-size slide

  47. DEMO
    Online Restaurant
    50
    Service

    View full-size slide

  48. DEMO
    Online Restaurant
    51

    View full-size slide

  49. EXAMPLE: ONLINE RESTAURANT
    52
    Online Restaurant
    Publishes
    Listen to

    View full-size slide

  50. EXAMPLE: ONLINE RESTAURANT
    53
    Online Restaurant
    Publishes
    Listen to
    Publishes Listen to

    View full-size slide

  51. TECHNOLOGIES
    Java
    Spring Boot
    Axon Framework
    Spring Data REST
    RabbitMQ
    54
    https://github.com/vvgomes/event-driven-restaurant

    View full-size slide

  52. MICROSERVICES + EVENT SOURCING
    Benefits
    •History based queries
    •Audit log by design
    •Immutability
    •User intent
    •Decoupling
    •Resilience
    56
    Challenges
    •Complexity
    •Snapshots
    •Upcasting
    •Race conditions
    •Event contracts
    •Eventual consistency

    View full-size slide

  53. WHEN
    MICROSERVICES
    MEET
    EVENT SOURCING
    Vinicius Gomes
    57

    View full-size slide