Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Akka Microservices Architecture And
Design
Yaroslav Tkachenko
Senior Software Engineer at Demonware (Activision)
@sap1ens
✋
Actors
● Communicate with asynchronous messages
instead of method invocations
● Manage their own state
● When responding to a mes...
📬 📬
📬
object MyActor {
case class Greeting(from: String)
case object Goodbye
}
class MyActor extends Actor with ActorLogging {
i...
Actor != Class
loop() ->
receive
{From, Msg} ->
io:format("received ~p~n", [Msg]),
From ! "got it";
end.
Erlang
object HelloWorld {
final case class Greet(whom: String, replyTo: ActorRef[Greeted])
final case class Greeted(whom: String...
Actor Systems
??? What the ...
● I know MVC!
● How do I do DI?
● What about that pattern X?
● Does it follow SOA?
● Microservices?
Domain-Driven Design
● Focus on core domain and business logic
● Base complex designs on the domain model
● Collaborate with domain experts (ub...
Tactical Patterns
Entity (Case Class)
● Account
● User
● Transaction
Value object (Trait)
● Checking | Savings | Credit Card
● Active | Inac...
Entities contain business logic only involving their own state.
We can also call this logic pure.
● Account.addBalance
● U...
Event (Actor Message - Case Class) is simply a fact that
something happened.
● AccountDeactivated(account)
● UserCreated(u...
Command (Actor Message - Case Class) is a direct
instruction for data manipulation, retrieval or a side-effect.
● Deactiva...
Repository (Actor OR Object/Class) is a way to access or
modify domain data and produce a set of entities.
● accountReposi...
Domain Services (Actors) manage multiple entities and/or
communicate with other services and repositories to
implement com...
How about Aggregate Roots?
We defined an Application Core, containing our Domain
model and business logic. We haven’t yet discussed:
● APIs
● Integra...
Application Services implement Adapter pattern and they’re
explicitly located outside of the Application Core. Usually
rep...
Strategical Patterns
How (assuming we should) do we split our Domain Model
into multiple [micro]services?
Domain
Bounded Context Bounded Context
Subdomain
Subdomain
Subdomain
Subdomain
Subdomain
Subdomain
Sweet spots for service...
Online education service
User Management Courses
User profiles
Achievements
Billing
Catalog
Content
management
Reviews
So, our [micro]services are:
- Completely isolated
- Deployed separately
- Have different actor systems
- Have clear bound...
Now we have multiple [micro]services running multiple actor
systems. How do they communicate?
- Synchronously, over HTTP/R...
It is unfortunate that synchronous HTTP is
widely considered as the go-to Microservice
communication protocol. Its synchro...
Messaging with actors
UserService
UserCreated
EmailSender
Service
SendEmail
Routing
QueueProducer
Adapter
QueueConsumer
Adapter
Core Core
Adapte...
Message routing is very specific to your domain:
- Use ActiveMQ/RabbitMQ by default and see if you can
survive with static...
EIP was published in 2003 and it contains 65 patterns.
Apache Camel:
- Integration framework based on EIP
- akka-camel is an official Akka library
- Can be used with any JVM lan...
class CustomerService extends Actor with ActorLogging with Consumer {
val camel = CamelExtension(system)
camel.context.add...
Apache Camel
Alpakka - Enterprise Integration Done Right ©
- Built in top of Akka Streams
- Back-pressure all the way
- St...
Stateful services
Stateful application service keeps all data inside the
application instead of an external storage (like database
or cache)...
Example, service requirements:
- Need to be really fast (low latency)
- Should have “strong” consistency (at least within ...
Which means:
- Might be very challenging to use a database
- Can’t use caching
- Solution: stateful service. Keeping data ...
Naive approach:
- Just keeping data in memory. Ok…
- Need to make service HA, running at least 2 nodes. Ok…
- Now we have ...
Akka Clustering is a cluster membership service:
- Gossip-based
- No SPOF
- Eventually consistent
- Failure detection buil...
Powerful collection of patterns for building distributed
applications:
- Cluster Routing
- Cluster Pub/Sub
- Cluster Singl...
Akka Persistence allows actors to persist internal state to an
external storage and recover after restarts and crashes:
- ...
Akka Cluster Sharding + Akka Persistence = ❤️
StatsService
1 3 5
StatsService
2 4 6
statsServiceRegion ! GetStats(userId)
Stateful services with Akka:
- Routing, sharding and recovery built-in
- You still just deal with actors!
- Akka Distribut...
It’s important to remember that Akka Clustering application
is still restricted by the bounded context (or subdomain) and
...
Summary
- Akka is great!
- Use Domain-Driven Design for modelling your application
core and understanding service boundaries
- Use...
Questions?
@sap1ens
sap1ens.com
Akka Microservices Architecture And Design
Akka Microservices Architecture And Design
Akka Microservices Architecture And Design
Akka Microservices Architecture And Design
Akka Microservices Architecture And Design
Akka Microservices Architecture And Design
Upcoming SlideShare
Loading in …5
×

Akka Microservices Architecture And Design

2,264 views

Published on

Nowadays Akka is a popular choice for building distributed systems - there are a lot of case studies and successful examples in the industry.
But it still can be hard to switch to actor-based systems, because most of the tutorials and documentation don't show the way to assemble a real application using actors, especially in microservices environment.

Actor is a powerful abstraction in the message-driven environments, but it can be challenging to use familiar patterns and methodologies. At the same time, message-driven nature of actors is the biggest advantage that can be used for Reactive systems and microservices.

I want to share my experience and show how Domain-Driven Design and Enterprise Integration Patterns can be leveraged to design and build fine-grained microservices with synchronous and asynchronous communication. I'll focus on the core Akka functionality, but also explain how advanced features like Akka Persistence and Akka Cluster Sharding can be used together for achieving incredible results.

Published in: Software
  • Be the first to comment

Akka Microservices Architecture And Design

  1. 1. Akka Microservices Architecture And Design Yaroslav Tkachenko Senior Software Engineer at Demonware (Activision) @sap1ens
  2. 2.
  3. 3. Actors
  4. 4. ● Communicate with asynchronous messages instead of method invocations ● Manage their own state ● When responding to a message, can: ○ Create other (child) actors ○ Send messages to other actors ○ Stop (child) actors or themselves
  5. 5. 📬 📬 📬
  6. 6. object MyActor { case class Greeting(from: String) case object Goodbye } class MyActor extends Actor with ActorLogging { import MyActor._ def receive = { case Greeting(greeter) => log.info(s"I was greeted by $greeter.") case Goodbye => log.info("Someone said goodbye to me.") } } val system = ActorSystem("mySystem") val myActor = system.actorOf(Props[MyActor], "myactor") myActor ! Greeting("another actor")
  7. 7. Actor != Class
  8. 8. loop() -> receive {From, Msg} -> io:format("received ~p~n", [Msg]), From ! "got it"; end. Erlang
  9. 9. object HelloWorld { final case class Greet(whom: String, replyTo: ActorRef[Greeted]) final case class Greeted(whom: String) val greeter = Actor.immutable[Greet] { (_, msg) ⇒ println(s"Hello ${msg.whom}!") msg.replyTo ! Greeted(msg.whom) Actor.same } } Akka Typed
  10. 10. Actor Systems
  11. 11. ??? What the ...
  12. 12. ● I know MVC! ● How do I do DI? ● What about that pattern X? ● Does it follow SOA? ● Microservices?
  13. 13. Domain-Driven Design
  14. 14. ● Focus on core domain and business logic ● Base complex designs on the domain model ● Collaborate with domain experts (ubiquitous language) ● Strategic and tactical patterns
  15. 15. Tactical Patterns
  16. 16. Entity (Case Class) ● Account ● User ● Transaction Value object (Trait) ● Checking | Savings | Credit Card ● Active | Inactive ● Debit | Credit
  17. 17. Entities contain business logic only involving their own state. We can also call this logic pure. ● Account.addBalance ● User.isDisabled ● Transaction.hasLedger
  18. 18. Event (Actor Message - Case Class) is simply a fact that something happened. ● AccountDeactivated(account) ● UserCreated(user) ● TransactionUpdated(transaction, transaction)
  19. 19. Command (Actor Message - Case Class) is a direct instruction for data manipulation, retrieval or a side-effect. ● DeactivateAccount(account) ● CreateUser(user) ● UpdateTransaction(transaction)
  20. 20. Repository (Actor OR Object/Class) is a way to access or modify domain data and produce a set of entities. ● accountRepository ! FindAccountById(id) ● userRepository ! UpdateUserName(id, name) ● transactionRepository ! FindAllTransactionsBetween(date, date)
  21. 21. Domain Services (Actors) manage multiple entities and/or communicate with other services and repositories to implement complex logic. They’re usually stateless. ● accountService ! DeactivateAccount(account) ● userService ! RegisterUser(name, email, type) ● transactionService ! MergeTransactions(transaction, transaction)
  22. 22. How about Aggregate Roots?
  23. 23. We defined an Application Core, containing our Domain model and business logic. We haven’t yet discussed: ● APIs ● Integrations ● Security ● etc.
  24. 24. Application Services implement Adapter pattern and they’re explicitly located outside of the Application Core. Usually represented as Actors. They can be responsible for: ● Communication via HTTP, RPC APIs, messaging queues ● Integrations with 3rd-party systems ● Security, caching, etc.
  25. 25. Strategical Patterns
  26. 26. How (assuming we should) do we split our Domain Model into multiple [micro]services?
  27. 27. Domain Bounded Context Bounded Context Subdomain Subdomain Subdomain Subdomain Subdomain Subdomain Sweet spots for service boundaries!
  28. 28. Online education service User Management Courses User profiles Achievements Billing Catalog Content management Reviews
  29. 29. So, our [micro]services are: - Completely isolated - Deployed separately - Have different actor systems - Have clear boundaries from DDD perspective
  30. 30. Now we have multiple [micro]services running multiple actor systems. How do they communicate? - Synchronously, over HTTP/RPC - Asynchronously, over messaging
  31. 31. It is unfortunate that synchronous HTTP is widely considered as the go-to Microservice communication protocol. Its synchronous nature introduces strong coupling between services which makes it a very bad default protocol for inter-service communication. Instead, communication between Microservices needs to be based on Asynchronous Message-Passing. Having an asynchronous boundary between services is necessary in order to decouple them, and their communication flow: • in time: for concurrency, and • in space: for distribution and mobility Bla bla microservices bla bla Jonas Bonér CTO of Lightbend
  32. 32. Messaging with actors
  33. 33. UserService UserCreated EmailSender Service SendEmail Routing QueueProducer Adapter QueueConsumer Adapter Core Core Adapters Adapters
  34. 34. Message routing is very specific to your domain: - Use ActiveMQ/RabbitMQ by default and see if you can survive with static topics/queues - Add custom middleware layer for routing (consumer and producer at the same time) - Use Kafka with Kafka Streams / Akka Streams
  35. 35. EIP was published in 2003 and it contains 65 patterns.
  36. 36. Apache Camel: - Integration framework based on EIP - akka-camel is an official Akka library - Can be used with any JVM language - “The most unknown coolest library out there” (©) JM
  37. 37. class CustomerService extends Actor with ActorLogging with Consumer { val camel = CamelExtension(system) camel.context.addComponent("activemq", ActiveMQComponent.activeMQComponent( "tcp://localhost:61616" )) def endpointUri = "activemq:topic:events" def receive = { case e: CamelMessage => { sender() ! "SomeMessage" } } }
  38. 38. Apache Camel Alpakka - Enterprise Integration Done Right © - Built in top of Akka Streams - Back-pressure all the way - Still in active development
  39. 39. Stateful services
  40. 40. Stateful application service keeps all data inside the application instead of an external storage (like database or cache) Why discuss stateful services?
  41. 41. Example, service requirements: - Need to be really fast (low latency) - Should have “strong” consistency (at least within one entity), no stale data - Should be highly available (HA) - Lots of data - [Maybe] very complex queries
  42. 42. Which means: - Might be very challenging to use a database - Can’t use caching - Solution: stateful service. Keeping data and application logic together
  43. 43. Naive approach: - Just keeping data in memory. Ok… - Need to make service HA, running at least 2 nodes. Ok… - Now we have duplicated data. How do we route requests? Sticky LB? Some partitioning? - Or what if our data volume is too big for one node? - We need to shard it. How? - Akka Cluster Sharding + Akka Persistence FTW!
  44. 44. Akka Clustering is a cluster membership service: - Gossip-based - No SPOF - Eventually consistent - Failure detection built-in
  45. 45. Powerful collection of patterns for building distributed applications: - Cluster Routing - Cluster Pub/Sub - Cluster Singleton - Cluster Sharding
  46. 46. Akka Persistence allows actors to persist internal state to an external storage and recover after restarts and crashes: - Event sourcing applied to an internal actor state - RDBMS, NoSQL, caches and and queues as storage - Snapshotting for fast recovery
  47. 47. Akka Cluster Sharding + Akka Persistence = ❤️
  48. 48. StatsService 1 3 5 StatsService 2 4 6 statsServiceRegion ! GetStats(userId)
  49. 49. Stateful services with Akka: - Routing, sharding and recovery built-in - You still just deal with actors! - Akka Distributed Data can be used instead of external storage
  50. 50. It’s important to remember that Akka Clustering application is still restricted by the bounded context (or subdomain) and it should be used within the microservice boundary.
  51. 51. Summary
  52. 52. - Akka is great! - Use Domain-Driven Design for modelling your application core and understanding service boundaries - Use Enterprise Integration Patterns for developing your asynchronous messaging design - Look at Akka Clustering and Persistence for complex problems with distributed services
  53. 53. Questions? @sap1ens sap1ens.com

×