Slide 1

Slide 1 text

Event-driven architecture Takeaway from the O’Reilly Software Architecture Conference

Slide 2

Slide 2 text

Overview ● Event-driven was a main theme in the recent O’Reilly Software Architecture conference in NYC ● It’s a fundamental change in the recommended way to build complex applications, to make them more scalable, resilient & extensible ● This talk will cover: ○ Why is it important ○ Some event-driven patterns ○ Links to notable talks from the conference

Slide 3

Slide 3 text

Why is it important

Slide 4

Slide 4 text

Procedural code & God services The way we’re used to do things ● Procedural code usually implements the full flow of some task, usually involving the invocation of few other functions & doing something with their results. ● Similarly, when writing services, we tend to create "God" services that implement a full flow, usually involving sync calls to other services.

Slide 5

Slide 5 text

Example: service handling an order Call payment service Order service Call procurement service Call shipment service Payment service Procurement service Shipment service

Slide 6

Slide 6 text

The problem: entangled services Other service is down When another service isn't responding or times-out, we need to retry the calls, using exponential backoff, or alternatively handle a back pressure logic Other service changes Every change in the invocation details of the other service requires us to change our service This creates a coupling between the services, and increases the complexity & cost of change New service is added When our service needs to call other services, any new service added to the flow requires us to change our service Think of few years from now, when this code will be legacy & someone will need to extend it

Slide 7

Slide 7 text

The problem: entangled services Other service is down When another service isn't responding or times-out, we need to retry the calls, using exponential backoff, or alternatively handle a back pressure logic Other service changes Every change in the invocation details of the other service requires us to change our service This creates a coupling between the services, and increases the complexity & cost of change New service is added When our service needs to call other services, any new service added to the flow requires us to change our service Think of few years from now, when this code will be legacy & someone will need to extend it Note that by services we mean Microservices, which are supposed to be very independent & decoupled!

Slide 8

Slide 8 text

Functional programming & Event-driven architecture A better way to do things ● Unlike procedural code, functional programming is based on a different paradigm, in which simple functions handle events & generate new events ● When applying this paradigm to services, we switch from "God" services to simple independent services interacting with each other using events

Slide 9

Slide 9 text

Procedural Functional A complex procedure implementing synchronously a full flow, using mutable state A function handling different types of input patterns, & generating outputs resulting in the flow

Slide 10

Slide 10 text

Example: services handling an order Order service Order Placed Payment service Order Paid Procurement service Items Ready Shipment service

Slide 11

Slide 11 text

The benefit: disentangled services Other service is down Services don’t need to wait for other services or retry calls Services are decoupled - they don’t need to know about other services & aren’t impacted by them Other service changes Every change in the invocation details of the other service does not require any change to our service Services are isolated from implementation changes of other services New service is added You can add more services without any change to your service Think of few years from now, when this code will be legacy & someone will need to extend it

Slide 12

Slide 12 text

Patterns

Slide 13

Slide 13 text

The basics Event-based interaction An event is a fact describing something that happened Services producing/sensing an event should publish it & any logic that needs to be triggered to handle the event, will be done in services who subscribe/listen to the event asynchronously The idea is to apply this to ANY interaction between services or applications - no direct calls, only events

Slide 14

Slide 14 text

The basics Transport layer If it’s within the firewall, any message bus or stream-processing transport (RabbitMQ, Kafka, AWS Kinesis) Outside the firewall, you can have an event delivery mechanism based on: - HTTP (poll for events) - Atom (AtomPub) - Websockets (connect to stream of events) - Webhooks (event listeners register their HTTP endpoint, like GitHub & Twillio do)

Slide 15

Slide 15 text

Materialized Views & CQRS Instead of querying other services for data Without events, services query other services for data, & have to deal with outage, latency, cache invalidation &c When using events, some services generate events (usually command handlers), & other services listen to these events & maintain a Materialized view of the data This pattern also solves the problem of joining data from multiple services (each having its own DB)

Slide 16

Slide 16 text

Sagas Choreographed dance across services Sometimes you need multiple service interactions that try to ensure some conditions are met A common example is when you need to implement a “transaction” across services - either the whole flow succeeds or everything rolls back Usually, this means that you’ll manage a state & update it across services until all conditions are met

Slide 17

Slide 17 text

Sagas An example An example “transaction” of processing an order using events:

Slide 18

Slide 18 text

Serverless functions PaaS λ-functions to handle events Event-driven architecture helps us build simple small services, handling a single function/concern This fits exactly to the serverless model of simple functions running on the cloud, triggered by events & generating further events Common example: AWS lambda function triggered whenever some input file is added to an S3 bucket

Slide 19

Slide 19 text

Stream processing frameworks Scalable & durable message bus, with high degree of freedom to change, adjust & adapt Using a message bus for events delivery results in a centralized immutable stream of facts, & decentralized services that process them This fits well frameworks like Apache Kafka & AWS Kinesis that provide: - Message durability - Scalable highly-available handling of events - Ability to divert/duplicate events - Use schemas for versioning

Slide 20

Slide 20 text

Events-based business-logic & persistence Events all the way Events represent a stream of changes, so when adapting to an event-driven architecture, you can also adapt the business logic & data-model to be based on streams of immutable changes instead of mutable data - AKA “event-sourcing”, it’s like the difference between data in a DB & in journal/op log This model makes things more simple, scalable & powerful, but is a big & radical change

Slide 21

Slide 21 text

Workflow engines Orchestrating event-driven services Stateless simple event-handling services can pose a problem when you have a flow that requires stateful orchestration To overcome this, you can use Workflow Engines, that model flows as a state-machine & manage the state of flows Every service has access to the current flow state, & can make decisions based on it

Slide 22

Slide 22 text

Workflow engines (continued) For example, if some service is down, the state-machine could define a retry logic, or fallback actions to deal with the outage Workflow engines allow you to define flows in a high-level manner, so you can evolve & manage complex flows, without changing multiple services They also allow you to monitor flows in production

Slide 23

Slide 23 text

Notable talks

Slide 24

Slide 24 text

Recommended talks on this topic from the conference Turning request-response on its head Cornelia Davis, Pivotal Events on the outside, inside & core Chris Richardson, Eventuate Complex event flows in distributed systems Bernd Ruecker, Camunda