Event Sourcing using Akka on AWS

54
EVENT‐DRIVEN‐ ARCHITECTURE ON AWS USING AKKA

Transcript of Event Sourcing using Akka on AWS

Page 1: Event Sourcing using Akka on AWS

EVENT‐DRIVEN‐ARCHITECTURE ONAWS USING AKKA

Page 2: Event Sourcing using Akka on AWS

Software Engineer @firstbird

Contact me: @pfeiffer_d_

DANIEL PFEIFFER

Page 3: Event Sourcing using Akka on AWS

THE JOURNEY OF EVENTSthat are stored with Akka Persistenceto be then distributed via AWSto be consumed with Akka Streamwhat comes after that

Page 4: Event Sourcing using Akka on AWS

THE EXAMPLE

Page 5: Event Sourcing using Akka on AWS

DOMAIN DRIVEN DESIGNWe are talking about Aggregates and Events

Page 6: Event Sourcing using Akka on AWS

EVENT SOURCING"Capture all changes to an application

state as a sequence of events" -Martin Fowler, 2005

Page 7: Event Sourcing using Akka on AWS

CQRS"Asking a question should not changethe answer." - Bertrand Meyer, 2012

Page 8: Event Sourcing using Akka on AWS

THE DIFFERENCE

Page 9: Event Sourcing using Akka on AWS

PERSISTENTACTORclass TimeEntryAggregate(id: String) extends PersistentActor{ override def persistenceId: String = ??? override def receiveCommand: Receive = ??? override def receiveRecover: Receive = ???}

Page 10: Event Sourcing using Akka on AWS

A PersistentActor class represents one DDDaggregate.

class TimeEntryAggregate(id: String) extends PersistentActor{ ... override def persistenceId: String = s"time-entry-$id" ...}

Page 11: Event Sourcing using Akka on AWS

A PersistentActor receives commands andpersists events.

case class CreateTimeEntry( begin: DateTime, end: DateTime)

case class TimeEntryCreated( begin: DateTime, end: DateTime, sequenceNr: Long)

Page 12: Event Sourcing using Akka on AWS

A PersistentActor receives commands andpersists events.

class TimeEntryAggregate(id: String) extends PersistentActor{ ... override def receiveCommand: Receive = case CreateTimeEntry(start, end) => val event = TimeEntryCreated(start,end, lastSequenceNr + 1) persist(event){e => // update internal state // here we go after the event is persisted } } ...}

Page 13: Event Sourcing using Akka on AWS

A PersistentActor recovers from the journalclass TimeEntryAggregate(id: String) extends PersistentActor{ ... override def receiveRecover: Receive = { case TimeEntryCreated(start,end) => // update internal state } ...}

Page 14: Event Sourcing using Akka on AWS

STORING EVENTS TO A JOURNALIS NICE, BUT ...

others may be as well interested, so we have todistribute them.

Page 15: Event Sourcing using Akka on AWS

WITHIN ONE JVM WE COULD...use Akka EventStream to publish events ...

class TimeEntryActor() extends PersistentActor{ ... persist(event){e => context.system.eventStream.publish(e) } ...}

Page 16: Event Sourcing using Akka on AWS

... and subscribe from interested actorsclass EventConsumer extends Actor{ override def preStart: Unit = { context.system.eventStream.subscribe(classOf[TimeEntryActor.TimeEntryCreated } override def receive: Receive = { case e: TimeEntryCreated => //do something with that event }}

Page 17: Event Sourcing using Akka on AWS

HOW DO I INTERACT WITH MYAGGREGATES?

Page 18: Event Sourcing using Akka on AWS

DON'T CALL ME! CALL MYOFFICE!

Page 19: Event Sourcing using Akka on AWS

EXAMPLE 1

Page 20: Event Sourcing using Akka on AWS

BUT WE WANT TO BE COOL

Page 21: Event Sourcing using Akka on AWS

DISTRIBUTED SYSTEMS AREHARD

Page 22: Event Sourcing using Akka on AWS

WE WANT TO MAKE THEMEASIER

Page 23: Event Sourcing using Akka on AWS

INTRODUCE A MESSAGEBROKER, PUB/SUB ...

Page 24: Event Sourcing using Akka on AWS

THE EXAMPLE ONAWS STEROIDS

Page 25: Event Sourcing using Akka on AWS
Page 26: Event Sourcing using Akka on AWS

TIME ENTRY SERVICE

Page 27: Event Sourcing using Akka on AWS

EMAIL SERVICE

Page 28: Event Sourcing using Akka on AWS

SQS FLOWSqsSource(...) .map(msg => Envelope(msg.receiptHandle, msg.body)) .via(unmarshal()) .via(process()) .runWith(ack(...))

Page 29: Event Sourcing using Akka on AWS

SQS MESSAGE{ "messageId" : "", "receiptHandle" : "", "md5OfBody" : "", "body" : ""}

Page 30: Event Sourcing using Akka on AWS

SNS NOTIFICATION ENVELOPE{ "Type" : "Notification", "MessageId" : "", "TopicArn" : "", "Subject" : "time_entry.approved", "Message" : "", "Timestamp" : "", "SignatureVersion" : "", "Signature" : "", "SigningCertURL" : "", "UnsubscribeURL" : ""}

Page 31: Event Sourcing using Akka on AWS

CHALLENGES

Page 32: Event Sourcing using Akka on AWS

EVENT SCHEMA EVOLUTIONadding a field to an event type,remove or rename field in event type,remove event type,split event into multiple smaller events.

Page 33: Event Sourcing using Akka on AWS

case class TimeEntryCreated( id: UUID, begin: DateTime, end: DateTime, timeEntryUserId: UUID, userId: UUID)

gets marshalled to{ "id" : "123456", "begin" : "2016-09-01 12:00:00", "end" : "2016-09-01 12:15:00", "timeEntryUserId" : "00000000-0000-0000-0000-000000000000", "userId" : "00000000-0000-0000-0000-000000000000"}

Page 34: Event Sourcing using Akka on AWS

Then something within our schema changescase class TimeEntryCreated( ... description: String ...)

and we will have fun with that one{ "id" : "123456", "begin" : "2016-09-01 12:00:00", "end" : "2016-09-01 12:15:00", "timeEntryUserId" : "00000000-0000-0000-0000-000000000000", "userId" : "00000000-0000-0000-0000-000000000000"}

Page 35: Event Sourcing using Akka on AWS

{ "id" : "123456", "begin" : "2016-09-01 12:00:00", "end" : "2016-09-01 12:15:00", "timeEntryUserId" : "00000000-0000-0000-0000-000000000000", "userId" : "00000000-0000-0000-0000-000000000000"}

needs to be transformed to that{ "id" : "123456", "begin" : "2016-09-01 12:00:00", "end" : "2016-09-01 12:15:00", "timeEntryUserId" : "00000000-0000-0000-0000-000000000000", "userId" : "00000000-0000-0000-0000-000000000000", "description" : "N/A"}

Page 36: Event Sourcing using Akka on AWS

class Evolution(system: ExtendedActorSystem) extends EventAdapter{} override def fromJournal(event: Any, manifest: String): EventSeq = { val es = ... //doing evolution on event EventSeq(es) } override def manifest(event: Any): String = { val version = ??? event.getClass.getSimpleName + ":" + version } override def toJournal(event: Any): Any = ??? //write to the journal}

Page 37: Event Sourcing using Akka on AWS

SCALING WITH AKKA CLUSTERON AWS

or "Who am I, and where are all the others?"

Page 38: Event Sourcing using Akka on AWS

JOINING A CLUSTER

gives you information about your instancehttp://169.254.169.254/latest/meta-data/instance-id

Page 39: Event Sourcing using Akka on AWS

PRESERVING MESSAGE ORDER

Page 40: Event Sourcing using Akka on AWS

The query side could look like that| id | ... | version || --- | --- | ------- || 1 | ... | 45 || 2 | ... | 3 || 3 | ... | 58 |

Page 41: Event Sourcing using Akka on AWS

CHOOSING THE RIGHTDATASTORE

you will make mistakes so plan for it

Page 42: Event Sourcing using Akka on AWS

ASYNCHRONOUS MEANS NOTIMMEDIATE

Page 43: Event Sourcing using Akka on AWS

WHY DO WE REALLY WANT TODO THAT?

Page 44: Event Sourcing using Akka on AWS

WE WANT TO SLEEP BETTER

Page 45: Event Sourcing using Akka on AWS

WE WANT TO GET RID OF OURMONOLITH

Page 46: Event Sourcing using Akka on AWS

OUR DEVELOPMENT PROCESS BENEFITS

Page 47: Event Sourcing using Akka on AWS

WE CAN ALWAYS AGGREGATE OUREVENTS

Page 48: Event Sourcing using Akka on AWS

IF SOMEONE STARTS TO ASKQUESTIONS...

An audit log is included in your application for free!

Page 49: Event Sourcing using Akka on AWS

SUMMARY

Page 50: Event Sourcing using Akka on AWS

THE FIRST PROTOTYPE IS EASY BUT TOTACKLE THE CHALLENGES NEEDS

EFFORT!

Page 51: Event Sourcing using Akka on AWS

CONFIGURE YOUR SQS QUEUESPROPERLY

Page 52: Event Sourcing using Akka on AWS

LET EACH SERVICE MANAGE IT'SRESOURCES ITSELF.

Page 53: Event Sourcing using Akka on AWS

ONE TOPIC PER AGGREGATE

Page 54: Event Sourcing using Akka on AWS

LITERATURE

https://www.infoq.com/articles/AmazonPubSubhttp://martinfowler.com/eaaDev/EventCollaboration.html

http://martinfowler.com/bliki/CQRS.htmlhttps://github.com/dpfeiffer/event-sourcing-aws-

akka-showcasehttp://www.oreilly.com/programming/free/reactive-

microservices-architecture.htmlhttp://doc.akka.io/docs/akka/snapshot/scala/persistence-

schema-evolution.html#persistence-schema-evolution-scala http://chrisloy.net/2014/05/11/akka-

cluster-ec2-autoscaling.html