#hacksummit 2016 - event-driven microservices – Events on the outside, on the inside and at the core

5,660 views

Published on

This is my presentation from #hacksummit 2016

This presentation looks at the importance of events and the role that they play in applications. We describe how events are a key application integration mechanism and how they are used by applications to communicate with the outside world. You will learn how the microservices inside a system can use events to maintain data consistency. We discuss how easy it is to implement both of these mechanisms by developing your core business logic using an event-centric approach known as event sourcing.

Published in: Software

#hacksummit 2016 - event-driven microservices – Events on the outside, on the inside and at the core

  1. 1. @crichardson Events on the outside, on the inside and at the core Chris Richardson Founder of Eventuate.io Founder of the original CloudFoundry.com Author of POJOs in Action @crichardson chris@chrisrichardson.net http://microservices.io http://eventuate.io http://plainoldobjects.com
  2. 2. @crichardson Presentation goal Events play a key role in applications Event sourcing enables the event-driven enterprise
  3. 3. @crichardson About Chris
  4. 4. @crichardson About Chris Consultant and trainer focusing on microservices (public class: April 28th, Oakland, CA) http://www.chrisrichardson.net/
  5. 5. @crichardson About Chris Founder of a startup that is creating a platform that makes it easy for application developers to write microservices http://eventuate.io
  6. 6. @crichardson For more information http://bit.ly/eventsfeb24
  7. 7. @crichardson Agenda Events on the outside Events on the inside Events at the core with event sourcing Designing event-centric domain model
  8. 8. @crichardson Events on the outside Application A Application B Application C Event X Event Y Event Z
  9. 9. @crichardson What’s an event? http://www.merriam-webster.com/dictionary/event
  10. 10. @crichardson Examples of events
  11. 11. @crichardson Instacart: event- driven grocery shopping
  12. 12. @crichardson An event is produced when… Creation or update of a business object Attempt to violate a business rule
  13. 13. @crichardson How to reliably generate events? More on that later…
  14. 14. @crichardson Who consumes an event? Order Application Human Notification Service Dashboard/ Monitoring Shipping Application OrderCreated Email SMS …
  15. 15. @crichardson How to deliver events?
  16. 16. @crichardson Inside the firewall
  17. 17. @crichardson Enterprise integration patterns http://www.enterpriseintegrationpatterns.com/patterns/messaging/
  18. 18. @crichardson messaging system Messaging-based IPC Sender RecipientChannel message
  19. 19. @crichardson Example messaging systems
  20. 20. @crichardson Outside the firewall
  21. 21. @crichardson Polling for events HTTP Periodically poll for events Atom Publishing Protocol (AtomPub) Based on HTTP Head is constantly changing Tail is immutable and can be efficiently cached High-latency, inefficient
  22. 22. @crichardson Using WebSockets Browser Web Socket STOMP Client application Service Web Socket STOMP Application SUBSCRIBE MESSAGE MESSAGE Low latency, more efficient, but what about past events?
  23. 23. @crichardson Webhooks = user-defined HTTP callback Client Service register(events, callbackUrl) POST callbackUrl POST callbackUrl … https://en.wikipedia.org/wiki/Webhook Low latency, more efficient, but what about past events?
  24. 24. @crichardson WebHooks = web friendly publish/subscribe
  25. 25. @crichardson Github webhooks https://developer.github.com/webhooks/ Installed on an organization or repository e.g. POST /repos/:owner/:repo/hooks Available events: push - push to a repository fork - repository is forked pull_request - assigned, unassigned, … push - push to a repository …
  26. 26. @crichardson Twilio - Telephony and SMS as a service Twilio Your Application TwiML doc HTTP GET/ POST REST API Manage resources Send SMS Initiate voice calls Webhooks handle incoming SMS and voice calls Voice SMS Phone number SMS URL +VOICE URL
  27. 27. @crichardson Integration hubs - Zapier, IFTTT Application abstraction: Triggers - events published by application: polling or Webhooks Action - operation supported by application, e.g. REST API end points
  28. 28. @crichardson The event-driven enterprise App A App BApp X App Y Firewall Message Broker webhooks WebSockets AtomPub App Z App C Msg Broker Client Msg Broker Client Msg Broker Client App D Msg Broker Client Inside the firewallOutside the firewall
  29. 29. @crichardson Agenda Events on the outside Events on the inside Events at the core with event sourcing Designing event-centric domain model
  30. 30. @crichardson Events on the inside Application Service A Service B Service C Event X Event YEvent Z Event X Event Y
  31. 31. @crichardson Traditional monolithic architecture Simple to develop test deploy scale Shopping Cart Customers Orders Mobile client REST API Browser Web UI Message Broker Adapter MySQL Adapter RDBMS … Message Broker
  32. 32. @crichardson But that leads* to monolithic hell For large and/or complex applications…
  33. 33. @crichardson Today: use a microservice, polyglot architecture Orders Customers … Shopping UI Mobile Client Browser API Gateway Order management REST API Customer Management REST API …. REST API Order Database (MongoDB) MongoDB Adapter Customer Database (Sharded MySQL) MySQL Adapter
  34. 34. @crichardson But now we have distributed data management problems
  35. 35. @crichardson Example: placing an order Order Service Customer Service Order Database Customer Database Order #1 Customer #1 No 2PC No ACID NoSQL SQL
  36. 36. @crichardson Customer management How to maintain invariants? Order management Order Service placeOrder() Customer Service updateCreditLimit() Customer creditLimit ... has ordersbelongs toOrder total Invariant: sum(open order.total) <= customer.creditLimit ?
  37. 37. @crichardson Use an event-driven architecture Services publish events when something important happens, e.g. state changes Services subscribe to events and update their state Maintain eventual consistency across multiple aggregates (in multiple datastores) Synchronize replicated data
  38. 38. @crichardson Event-driven application architecture Application Service A Service B Message Broker Service C Msg Broker Client Msg Broker Client Msg Broker Client Service D Msg Broker Client
  39. 39. @crichardson Order Management Order id : 4567 total: 343 state = CREATED Customer Management Customer creditLimit : 12000 creditReservations: {} Customer creditLimit : 12000 creditReservations: { 4567 -> 343} Order id : 4567 total: 343 state = OPEN Eventually consistent credit checking Message Bus createOrder() Publishes: Subscribes to: Subscribes to: publishes: OrderCreatedEvent CreditReservedEvent OrderCreatedEvent CreditReservedEvent
  40. 40. @crichardson Now there are two problems to solve….
  41. 41. @crichardson Problem #1: How to design eventually consistent business logic? More on that later….
  42. 42. @crichardson Problem #2: How to atomically update database and publish an event Order Service Order Database Message Broker insert Order publish OrderCreatedEvent dual write problem ?
  43. 43. @crichardson Failure = inconsistent system Order Service Order Database Message Broker insert Order publish OrderCreatedEvent X
  44. 44. @crichardson Two-phase commit X
  45. 45. @crichardson Agenda Events on the outside Events on the inside Events at the core with event sourcing Designing event-centric domain model
  46. 46. @crichardson Just publish events Application Database Message Broker update publish X
  47. 47. @crichardson Event sourcing For each aggregate (business entity): Identify (state-changing) domain events Define Event classes For example, ShoppingCart: ItemAddedEvent, ItemRemovedEvent, OrderPlacedEvent Order: OrderCreated, OrderCancelled, OrderApproved, OrderRejected, OrderShipped
  48. 48. @crichardson Persists events NOT current state Order status …. 101 ACCEPTED Order table X
  49. 49. @crichardson Persists events NOT current state Event table Entity type Event id Entity id Event data Order 902101 …OrderApproved Order 903101 …OrderShipped Event type Order 901101 …OrderCreated
  50. 50. @crichardson Replay events to recreate state Order state OrderCreated(…) OrderAccepted(…) OrderShipped(…) Events Periodically snapshot to avoid loading all events
  51. 51. @crichardson The present is a fold over history currentState = foldl(applyEvent, initialState, events)
  52. 52. @crichardson Events at the core Aggregate A Aggregate B Aggregate C Event X Event YEvent Z Event Z Event Y Service
  53. 53. @crichardson Domain logic = event-driven aggregates Customer AggregateOrder Aggregate Order Created Event Check Credit Command Credit Reserved Event Approve Order Command Create Order Command External request Emits events Event Command
  54. 54. @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 apply(newEvents)
  55. 55. @crichardson Event Store publishes events consumed by other services Event Store Event Subscriber subscribe(EventTypes) publish(event) publish(event) Customer update() Customer Service
  56. 56. @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 …
  57. 57. Event store = database + message broker Hybrid database and message broker Implementations: Home-grown/DIY geteventstore.com by Greg Young http://eventuate.io (mine) Event Store Save aggregate events Get aggregate events Subscribe to events
  58. 58. @crichardson Benefits of event sourcing Solves data consistency issues in a Microservice/NoSQL based architecture Reliable event publishing: publishes events needed by predictive analytics etc, user notifications,… Eliminates O/R mapping problem (mostly) Reifies state changes: Built in, reliable audit log, temporal queries Preserved history More easily implement future requirements
  59. 59. @crichardson Drawbacks of event sourcing… Requires application rewrite Weird and unfamiliar style of programming Events = a historical record of your bad design decisions Must detect and ignore duplicate events Idempotent event handlers Track most recent event and ignore older ones …
  60. 60. @crichardson … Drawbacks of event sourcing Querying the event store can be challenging Some queries might be complex/inefficient, e.g. accounts with a balance > X Event store might only support lookup of events by entity id Must use Command Query Responsibility Segregation (CQRS) to handle queries application must handle eventually consistent data
  61. 61. @crichardson Agenda Events on the outside Events on the inside Events at the core with event sourcing Designing event-centric domain model
  62. 62. @crichardson Use the familiar building blocks of DDD Entity Value object Services Repositories Aggregates ⟸ essential
  63. 63. About Aggregates Graph consisting of a root entity and one or more other entities and value objects Each core business entity = Aggregate: e.g. customer, Account, Order, Product, …. Reference other aggregate roots via primary key Often contains partial copy of other aggregates’ data Order OrderLine Item quantity productId productName productPrice customerId Address street city …
  64. 64. @crichardson Domain model = collection of loosely connected aggregates Order OrderLine Item quantity … Address street city … Customer Product name price
  65. 65. @crichardson Product service Customer serviceOrder service Easily partition into microservices Order OrderLine Item quantity … Address street city … Customer Product name price
  66. 66. @crichardson Transaction = processing one command by one aggregate No opportunity to update multiple aggregates within a transaction event driven eventual consistency between aggregates If an update must be atomic (i.e. no compensating transaction) then it must be handled by a single aggregate Therefore, aggregate granularity is important
  67. 67. @crichardson Product service Customer serviceOrder service Transaction scope = service Order OrderLine Item quantity … Address street city … Customer Product name price
  68. 68. @crichardson Aggregate granularity Consistency Scalability/ User experience Customer Order Product Customer Order Product Customer Order Product
  69. 69. Designing domain events Record state changes for an aggregate Part of the public API of the domain model ProductAddedToCart id : TimeUUID senderId: UUID productId productName productPrice … Required by aggregate Enrichment: Useful for consumers Event metadata
  70. 70. @crichardson Example event
  71. 71. @crichardson Designing commands Created by a service from incoming request Processed by an aggregate Immutable Contains value objects for Validating request Creating event Auditing user activity
  72. 72. @crichardson Example command
  73. 73. @crichardson Various programming models “Traditional Java” mutable object-oriented domain objects https://github.com/cer/event-sourcing-examples/tree/master/ java-spring Functional Scala with immutable domain objects https://github.com/cer/event-sourcing-using-scala-typeclasses Hybrid OO/Functional Scala with immutable domain objects https://github.com/cer/event-sourcing-examples/tree/master/ scala-spring
  74. 74. @crichardson OO = State + Behavior creditLimit creditReservations : Map<OrderId, Money> Customer List<Event> process(CreateCustomerCommand cmd) { … } List<Event> process(ReserveCreditCommand cmd) { … } … void apply(CustomerCreatedEvent anEvent) { … } void apply(CreditServedEvent anEvent) { … } … State Behavior
  75. 75. @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 … new CreditReservedCredit(); } public void apply( CreditReservedCredit event) { // update state this.xyz = event.xyz }
  76. 76. @crichardson Real-time, collaborative Kanban Board
  77. 77. @crichardson Kanban domain model Board title createdBy … Task title state …
  78. 78. @crichardson Architecture Create/update boards and tasks Change notifications Materialized views Event Store
  79. 79. @crichardson Request and event flow Eventuate event store Kanban Server AngularJS application POST /tasks/xyz/start Task xyz POST /entity/…. Task StartedAngularJS application WebSocket Message STOMP Message
  80. 80. @crichardson Demo
  81. 81. @crichardson Summary Events are a central to modern applications Events integrate applications Events maintain data consistency in a microservices architecture Build events into the core of your application using event sourcing
  82. 82. @crichardson For more information http://bit.ly/eventsfeb24
  83. 83. @crichardson @crichardson chris@chrisrichardson.net http://bit.ly/eventsfeb24 Questions?

×