1 / 60

How we Scale using Play , Akka , and Scala

How we Scale using Play , Akka , and Scala. Who are we?. Ryan Knight Consultant. Brian Pugh VP of Engineering. Lucidchart : Online diagramming solution. Lucidchart’s Story. … Lucidchart was in a precarious situation. Threat #1: Scaling.

lawson
Download Presentation

How we Scale using Play , Akka , and Scala

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. How we Scale using Play, Akka, and Scala

  2. Who are we? • Ryan Knight • Consultant • Brian Pugh • VP of Engineering

  3. Lucidchart: Online diagramming solution

  4. Lucidchart’s Story

  5. …Lucidchartwas in a precarious situation

  6. Threat #1: Scaling • Webservers scaled horizontally but required a large number of instances • DB scaled vertically which becomes prohibitively expensive

  7. Threat #2: Performance Minimum and average response times too high

  8. Threat #3: Availability Monolithic app: Any functional area of the application could take down the entire site 99.99999999999

  9. Significant change was needed!

  10. Identified 8 architectural goals

  11. 1. Service-Oriented Architecture

  12. 2. Little, if any, server side state

  13. 3. All data sharded

  14. 4. Persistence layer that allowed us to control queries

  15. 5. Great library support

  16. 6. Good runtime monitoring

  17. 7. Efficient development environment

  18. 8. Good support for parallel processing

  19. Evaluated Various Languages and Frameworks

  20. And the winner is…

  21. What is Scala? Agile, with lightweight syntax Object-oriented Functional Safe and performant, with strong static typing

  22. Why Scala?

  23. What is Play?

  24. Play Features

  25. What is Akka?

  26. Akka Actors

  27. Actors: Distributable by design

  28. FailureRecovery

  29. Typesafe Activator

  30. How does the Typesafe platform measure up to Lucidchart’s goals?

  31. valroleIds = SQL("SELECT role_id FROM users_roles WHERE user_id={user_id}") .on("user_id" -> id) .as(get[Long]("role_id") *)

  32. Benefits: Concise code

  33. Immutable Person Class in Java public class Person { private final String name; private final intiq; public Person(String name, intiq) { this.name = name; this.iq = iq; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (iq != person.iq) return false; if (name != null ? !name.equals(person.name) : person.name != null) return false; return true; } public inthashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + iq; return result; } public String getName() { return name; } public intgetIq() { return iq; } public String toString() { return "Person{" + "name='" + name + '\'' + ", iq=" + iq +'}'; } }

  34. Immutable Person Class in Scala case class Person(name: String, iq: Int)

  35. Functions as first class citizens • Filter users based on subscription rules • 71 lines of PHP code vs. 10 lines below levelPrefix.foreach { prefix => valvalidLevelIds =allLevels.filter( _.name.startsWith(prefix) ).filter(levelTermAnnual.isEmpty || _.annual == levelTermAnnual.get).map(_.id) allIds= allIds.filter { case UserModel.UserIdData(id, account_id, email) => if(prefix == "free") !subscriptions.contains(account_id) else subscriptions.get(account_id).map(s => validLevelIds.contains(s.level_id)).getOrElse(false) } }

  36. Does a string have an upper case character booleanhasUpperCase = false for (inti = 0; i< name.length(); i++) { if (Character.isUpperCase(name.charAt(i))) { hasUpperCase = true; break; } }

  37. Does a string have an upper case character valhasUpperCase = name.exists(_.isUpper)

  38. Benefits: Parallel Processing • Functional style encourages immutability • Actors and Futures provide a simpler mental model for concurrency • Using significant concurrency; haven’t had significant bugs related to it • Not the norm

  39. Benefits: Parallel Processing

  40. Example: Processing pages //Send a message with each page valpageFutures = pages.map{ page => ask(pageRouter, new PageGeneratorMessage(page)).mapTo[Page] } //get the results valpdfPages= Future.sequence(pageFutures).map { future => future.getPdf } … //create actor class PageGeneratorextends Actor { def receive = { case m: PageGeneratorMessage => sender ! generatePage(m.getPage) case _ => Logger.error("Unknown message " + m.toString) } … }

  41. Benefits: Type safe (with great inference) • A class of errors is guaranteed not to exist • More confident refactoring • Coming into a large codebase, types help with readability of code base

  42. Benefits: Performance Image Generation service • Average response time decreased by 53% • Median response time decreased by 37%

More Related