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.
Lightbend Lagom
Microservices “Just Right”
Mirco Dotta
@mircodotta
Scala Days NYC - May 10, 2016
Lagom - [lah-gome]
Adequate, sufficient, just right
Agenda
● Why Lagom?
● Lagom dive in
○ Development Environment
○ Service API
○ Persistence API
● Running in Production
Why Lagom?
● Opinionated
● Developer experience matters!
○ No brittle script to run your services
○ Inter-service communic...
● sbt build tool (developer experience)
● Play 2.5
● Akka 2.4 (clustering, streams, persistence)
● Cassandra (default data...
Enough slides,
Demo time
Anatomy of a Lagom project
● sbt build
● Scala 2.11 and JDK8
● Each service definition is split into two sbt projects:
○ a...
Service API
Service definition
trait HelloService extends Service {
override def descriptor(): Descriptor = {
named("helloservice").`w...
ServiceCall explained
● ServiceCall can be invoked when consuming a service:
○ Request: type of incoming request message (...
Strict Messages
Strict messages are fully buffered into memory
override def descriptor(): Descriptor = {
named("friendserv...
Streamed Messages
override def descriptor(): Descriptor = {
named("clock").`with`(
pathCall("/tick/:interval", tick())
)
}...
Remember the Service definition?
trait HelloService extends Service {
override def descriptor(): Descriptor = {
named("hel...
Here is the Service implementation
class HelloServiceImpl extends HelloService {
override def sayHello(): ServiceCall[Stri...
Inter-service communication
class MyServiceImpl @Inject()(helloService: HelloService)
(implicit ec: ExecutionContext) exte...
Persistence API
Principles
● Each service owns its data
○ Only the service has direct access to the DB
● We advocate the use of Event Sour...
Benefits of Event Sourcing/CQRS
● Allows you to time travel
● Audit log
● Future business opportunities
● No need for ORM
...
Event Sourcing: Write Side
● Create your own Command and Event classes
● Subclass PersistentEntity
○ Define Command and Ev...
Event Sourcing: Example
Create the Command classes
sealed trait FriendCommand extends Jsonable
case class AddFriend(friend...
Event Sourcing: Example cont’d
Create the Event classes
sealed trait FriendEvent extends Jsonable
case class FriendAdded(u...
Event Sourcing: Example cont’d
class FriendEntity extends
PersistentEntity[FriendCommand, FriendEvent, FriendState] {
def ...
Event Sourcing: Example cont’d
val b: Behavior = newBehaviorBuilder(/*...*/)
b.setCommandHandler(classOf[AddFriend],
(cmd:...
b.setEventHandler(classOf[FriendAdded],
(evt: FriendAdded) => state.addFriend(evt.friendId))
Event Sourcing: Example cont’...
Event Sourcing: Example cont’d
Create the State class
case class FriendState(user: Option[User]) extends Jsonable {
def ad...
class FriendServiceImpl @Inject() (persistentEntities: PersistentEntityRegistry)
(implicit ec: ExecutionContext) extends F...
Event Sourcing: Read Side
● Tightly integrated with Cassandra
● Create the query tables:
○ Subclass CassandraReadSideProce...
Running in Production
● sbt-native packager is used to produce zip, MSI, RPM, Docker
● Lightbend ConductR* (our container ...
Current[Lagom]
● Current version is 1.0.0-M2
○ 1.0 soon
● Java API, but no Scala API yet
○ We are working on the Scala API...
Future[Lagom]
● Maven support
● Message broker integration
● Scala API
● Support for other cluster orchestration tools
● S...
Next: Seq[Step]
● Try Lagom yourself
○ https://lightbend.com/lagom
● Using Scala with Lagom
○ https://github.com/dotta/act...
Thank you for listening!
@mircodotta
@lagom
override def descriptor(): Descriptor = {
named("friendservice").`with`(
namedCall("/users", createUser _),
pathCall("/use...
Upcoming SlideShare
Loading in …5
×

Lightbend Lagom: Microservices Just Right

6,709 views

Published on

Microservices architecture are becoming a de-facto industry standard, but are you satisfied with the current state of the art? We are not, as we believe that building microservices today is more challenging than it should be. Lagom is here to take on this challenge. First, Lagom is opinionated and it will take some of the hard decisions for you, guiding you to produce microservices that adheres to the Reactive tenents. Second, Lagom was built from the ground up around you, the developer, to push your productivity to the next level. If you are familiar with the Play Framework's development environment, imagine that but tuned for building microservices; we are sure you are going to love it! Third, Lagom comes with batteries included for deploying in production: going from development to production could not be easier. In this session, you will get an introduction to the Lightbend Lagom framework. There will be code and live demos to show you in practice how it works and what you can do with it, making you fully equipped to build your next microservices with Lightbend Lagom!

Published in: Software
  • I can advise you this service - ⇒ www.HelpWriting.net ⇐ Bought essay here. No problem.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Lightbend Lagom: Microservices Just Right

  1. 1. Lightbend Lagom Microservices “Just Right” Mirco Dotta @mircodotta Scala Days NYC - May 10, 2016
  2. 2. Lagom - [lah-gome] Adequate, sufficient, just right
  3. 3. Agenda ● Why Lagom? ● Lagom dive in ○ Development Environment ○ Service API ○ Persistence API ● Running in Production
  4. 4. Why Lagom? ● Opinionated ● Developer experience matters! ○ No brittle script to run your services ○ Inter-service communication just works ○ Services are automatically reloaded on code change ● Takes you through to production deployment
  5. 5. ● sbt build tool (developer experience) ● Play 2.5 ● Akka 2.4 (clustering, streams, persistence) ● Cassandra (default data store) ● Jackson (JSON serialization) ● Guice (DI) ● Architectural Concepts: immutability, Event Sourcing/CQRS, circuit breakers Under the hood
  6. 6. Enough slides, Demo time
  7. 7. Anatomy of a Lagom project ● sbt build ● Scala 2.11 and JDK8 ● Each service definition is split into two sbt projects: ○ api ○ Implementation
  8. 8. Service API
  9. 9. Service definition trait HelloService extends Service { override def descriptor(): Descriptor = { named("helloservice").`with`( namedCall("/hello", sayHello _) ) } def sayHello(): ServiceCall[String, String] } // this source is placed in your api project
  10. 10. ServiceCall explained ● ServiceCall can be invoked when consuming a service: ○ Request: type of incoming request message (e.g. String) ○ Response: type of outgoing response message (e.g. String) ● JSON is the default serialization format for request/response messages ● There are two kinds of request/response messages: ○ Strict ○ Streamed trait ServiceCall[Request, Response] { def invoke(request: Request): Future[Response] }
  11. 11. Strict Messages Strict messages are fully buffered into memory override def descriptor(): Descriptor = { named("friendservice").`with`( pathCall("/users/:userId/friends", addFriend _) ) } def addFriend(userId: String): ServiceCall[FriendId, NotUsed]
  12. 12. Streamed Messages override def descriptor(): Descriptor = { named("clock").`with`( pathCall("/tick/:interval", tick()) ) } def tick(): ServiceCall[String, Source[String, _]] ● A streamed message is of type Source (an Akka streams API) ● It allows asynchronous streaming and handling of messages ● Lagom will select transport protocol (currently WebSockets)
  13. 13. Remember the Service definition? trait HelloService extends Service { override def descriptor(): Descriptor = { named("helloservice").`with`( namedCall(sayHello _) ) } def sayHello(): ServiceCall[String, String] } // this source is placed in your api project
  14. 14. Here is the Service implementation class HelloServiceImpl extends HelloService { override def sayHello(): ServiceCall[String, String] { name => Future.successful(s"Hello, $name!") } } // this source is placed in your implementation project
  15. 15. Inter-service communication class MyServiceImpl @Inject()(helloService: HelloService) (implicit ec: ExecutionContext) extends MyService { override def sayHelloLagom(): ServiceCall[NotUsed, String] = unused => { val response = helloService.sayHello().invoke("Lagom") response.map(answer => s"Hello service said: $answer") } }
  16. 16. Persistence API
  17. 17. Principles ● Each service owns its data ○ Only the service has direct access to the DB ● We advocate the use of Event Sourcing (ES) and CQRS ○ ES: Capture all state’s changes as events ○ CQRS: separate models for write and read
  18. 18. Benefits of Event Sourcing/CQRS ● Allows you to time travel ● Audit log ● Future business opportunities ● No need for ORM ● No database migration script, ever ● Performance & Scalability ● Testability & Debuggability
  19. 19. Event Sourcing: Write Side ● Create your own Command and Event classes ● Subclass PersistentEntity ○ Define Command and Event handlers ○ Can be accessed from anywhere in the cluster ○ (corresponds to an Aggregate Root in DDD)
  20. 20. Event Sourcing: Example Create the Command classes sealed trait FriendCommand extends Jsonable case class AddFriend(friendUserId: String) extends PersistentEntity.ReplyType[Done] with FriendCommand // more friend commands
  21. 21. Event Sourcing: Example cont’d Create the Event classes sealed trait FriendEvent extends Jsonable case class FriendAdded(userId: String, friendId: String, timestamp: Instant = Instant.now()) extends FriendEvent // more friend events
  22. 22. Event Sourcing: Example cont’d class FriendEntity extends PersistentEntity[FriendCommand, FriendEvent, FriendState] { def initialBehavior(snapshotState: Optional[FriendState]): Behavior = // TODO: define command and event handlers } Create a subclass of PersistentEntity
  23. 23. Event Sourcing: Example cont’d val b: Behavior = newBehaviorBuilder(/*...*/) b.setCommandHandler(classOf[AddFriend], (cmd: AddFriend, ctx: CommandContext[Done]) => state.user match { case None => ctx.invalidCommand(s"User ${entityId} is not created") ctx.done() case Some(user) => ctx.thenPersist(FriendAdded(user.userId, cmd.friendUserId), (evt: FriendAdded) => ctx.reply(Done)) })
  24. 24. b.setEventHandler(classOf[FriendAdded], (evt: FriendAdded) => state.addFriend(evt.friendId)) Event Sourcing: Example cont’d No side-effects in the event handler!
  25. 25. Event Sourcing: Example cont’d Create the State class case class FriendState(user: Option[User]) extends Jsonable { def addFriend(friendUserId: String): FriendState = user match { case None => throw new IllegalStateException( "friend can't be added before user is created") case Some(user) => val newFriends = user.friends :+ friendUserId FriendState(Some(user.copy(friends = newFriends))) } }
  26. 26. class FriendServiceImpl @Inject() (persistentEntities: PersistentEntityRegistry) (implicit ec: ExecutionContext) extends FriendService { // at service startup we must register the needed entities persistentEntities.register(classOf[FriendEntity]) def addFriend(userId: String): ServiceCall[FriendId, NotUsed] = request => { val ref = persistentEntities.refFor(classOf[FriendEntity], userId) ref.ask[Done, AddFriend](AddFriend(request.friendId)) } // ... } Event Sourcing: Example cont’d
  27. 27. Event Sourcing: Read Side ● Tightly integrated with Cassandra ● Create the query tables: ○ Subclass CassandraReadSideProcessor ○ Consumes events produced by the PersistentEntity and updates tables in Cassandra optimized for queries ● Retrieving data: Cassandra Query Language ○ e.g., SELECT id, title FROM postsummary
  28. 28. Running in Production ● sbt-native packager is used to produce zip, MSI, RPM, Docker ● Lightbend ConductR* (our container orchestration tool) ● Lightbend Reactive Platform* ○ Split Brain Resolver (for Akka cluster) ○ Lightbend Monitoring *Requires a Lightbend subscription (ConductR is free to use during development)
  29. 29. Current[Lagom] ● Current version is 1.0.0-M2 ○ 1.0 soon ● Java API, but no Scala API yet ○ We are working on the Scala API ○ But using Scala with the Java API works well! https: //github.com/dotta/activator-lagom-scala-chirper
  30. 30. Future[Lagom] ● Maven support ● Message broker integration ● Scala API ● Support for other cluster orchestration tools ● Support for writing integration tests ● Swagger integration ○ Which also removes binary coupling!
  31. 31. Next: Seq[Step] ● Try Lagom yourself ○ https://lightbend.com/lagom ● Using Scala with Lagom ○ https://github.com/dotta/activator-lagom-scala-chirper ● Lagom on Github ○ https://github.com/lagom/lagom ● Read Jonas Bonér's free book Reactive Services Architecture ○ https://lightbend.com/reactive-microservices-architecture ● Great presentation by Greg Young on why you should use ES ○ https://www.youtube.com/watch?v=JHGkaShoyNs
  32. 32. Thank you for listening! @mircodotta @lagom
  33. 33. override def descriptor(): Descriptor = { named("friendservice").`with`( namedCall("/users", createUser _), pathCall("/users/:id", getUser _), restCall(Method.POST, "/users/:userId/friends", addFriend _) ) } def createUser(): ServiceCall[User, NotUsed] def getUser(id: String): ServiceCall[NotUsed, User] def addFriend(userId: String): ServiceCall[FriendId, NotUsed] Different kinds of service call descriptors

×