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 in Action workshop #ScalaMatsuri 2018

771 views

Published on

ScalaMatsuri2018

Published in: Technology
  • Be the first to comment

Akka in Action workshop #ScalaMatsuri 2018

  1. 1. Copyright © 2018 TIS Inc. All rights reserved. Akka in Action workshop Scala Matsuri 2018 Yugo Maede @yugolf The preparation for this workshop. https://github.com/akka-ja/akka-in-action/tree/matsuri/chapter-up-and-running#the-preparation
  2. 2. Copyright © 2018 TIS Inc. All rights reserved. 2 Who am I? Yugo Maede @yugolf TIS Inc. research and development using Akka, Scala and others Translated Akkaを使ったシステム開発や研究活動をやっています。 仲間募集開始!! We are recruiting colleagues to work together with us.
  3. 3. Copyright © 2018 TIS Inc. All rights reserved. 3 TISカジュアルはじめました 2018.3.1 TIS casual has started! We are hiring!
  4. 4. Copyright © 2018 TIS Inc. All rights reserved. 4 Todayʼs Topics Building a minimal Akka app The first step for Akka • How to implement Apps by using Akka • How to study Akka for the future Akkaで最⼩のアプリケーションを構築する  Akkaを使った実装の取っ掛かりに
  5. 5. Copyright © 2018 TIS Inc. All rights reserved. 5 Material 教材は『Akka実践バイブル』 ✦here
  6. 6. Copyright © 2018 TIS Inc. All rights reserved. 6 Akka in Action 『Akka実践バイブル』の内容 Appendix. Using Akka from Java https://www.manning.com/books/akka-in-action
  7. 7. Copyright © 2018 TIS Inc. All rights reserved. 7 Agenda • Introduction • Chapter1. Introducing Akka • Chapter2. Up and running • Fetching a project template • Building a minimal Akka app for the cloud 4 exercises • Deploying to Heroku • Conclusion アジェンダ
  8. 8. Copyright © 2018 TIS Inc. All rights reserved. Chapter 1. Introducing Akka 8 第1章 Akkaの紹介
  9. 9. Copyright © 2018 TIS Inc. All rights reserved. 9 Chapter 1. Introducing Akka Akkaとは/概要/従来型との違い/アクターのプログ ラミングモデル/Akkaのアクター 1.1. What is Akka? 1.2. Actors: a quick overview 1.3. Two approaches to scaling: setting up our example 1.4. Traditional scaling 1.5. Scaling with Akka 1.6. Actors: one programming model to rule up and out 1.7. Akka actors
  10. 10. Copyright © 2018 TIS Inc. All rights reserved. 10 What is Akka? Akkaは並⾏・分散アプリケーションのためのツール キット •The toolkit for concurrent and distributed applications •scale applications both up and out on the JVM •keep the complexity relatively low while an application scales
  11. 11. Copyright © 2018 TIS Inc. All rights reserved. 11 Actors: a quick overview アクターからアクターへメッセージを送信、受信した メッセージを到着順に処理 User Actor processes messages in order of arrival TicketSeller Buy Buy Buy mailbox ticketSeller ! Buy(tickets)
  12. 12. Copyright © 2018 TIS Inc. All rights reserved. 12 Traditional scaling and Akka scaling アクターと伝統的なアプローチの⽐較 • Traditional • Akka
  13. 13. Copyright © 2018 TIS Inc. All rights reserved. 13 Traditional scaling and Akka scaling ゴール:データは永続性あるものに、機能はインタラク ティブに、サービスは疎結合に、そして障害に強く Goal Traditional approach Akka approach Make data durable, even if the application restarts or crashes. Use the database as one big shared mutable state. Continue to use in-memory state. Changes to the state are sent as messages to a log. Provide interactive features Poll the database, even if there’s no change in the data. Push events to interested parties, only when there’s a significant event. Decoupling of services Add a message queue for asynchronous processing. No need to add a message queue; actors are asynchronous by definition. Prevent failure of the total system when critical services fail predicting all failure scenarios and catching exceptions. no impact on the stability of the other components.
  14. 14. Copyright © 2018 TIS Inc. All rights reserved. 14 Actors: one programming model to rule up and out 単⼀のプログラミングモデルでスケールアップとスケー ルアウトを実現 The actor model decouples from the number of threads or the number of servers.
  15. 15. Copyright © 2018 TIS Inc. All rights reserved. 15 Akka actors: Actor System Akkaのアクターはアクターシステムを作成することか ら https://doc.akka.io/docs/akka/2.5/general/supervision.html val system = ActorSystem("TeamChat")
  16. 16. Copyright © 2018 TIS Inc. All rights reserved. 16 Akka actors: ActorRef and Mailbox and Actor ActorRefに到着したメッセージは⼀時的にメールボッ クスに保存し到着順に処理する
  17. 17. Copyright © 2018 TIS Inc. All rights reserved. Chapter 2. Up and running 17 第2章 最⼩のAkkaアプリケーション
  18. 18. Copyright © 2018 TIS Inc. All rights reserved. Chapter 2. Up and running 18 •Fetching a project template •Building a minimal Akka app for the cloud •Deploying to Heroku 第2章 最⼩のAkkaアプリケーション • プロジェクトテンプレートの取得
  19. 19. Copyright © 2018 TIS Inc. All rights reserved. 19 Fetching a project template Gitからプロジェクトを取得してアプリケーションを実⾏ • Clone the example project from github.com $git clone https://github.com/akka-ja/akka-in-action.git $cd akka-in-action/chapter-up-and-running/ $sbt run https://github.com/akka-ja/akka-in-action/tree/matsuri/chapter-up-and-running#the-commands-using-this-workshop • Start the app [info] Running com.goticks.Main INFO [Slf4jLogger]: Slf4jLogger started INFO [go-ticks]: RestApi bound to /0:0:0:0:0:0:0:0:5000 INFO [go-ticks]: Success to bind to 0.0.0.0:5000
  20. 20. Copyright © 2018 TIS Inc. All rights reserved. 20 The structure of the project プロジェクトの構造 configuration files and other resources source codes test codes built files for building by sbt for executing on Heroku https://www.jetbrains.com/idea/download/
  21. 21. Copyright © 2018 TIS Inc. All rights reserved. 21 Ticket-selling service チケット販売サービス イベント作成/キャンセル/⼀覧取得/チケット購⼊ • Get all events • Buy tickets • Create an event • Cancel an event Ticket-selling service
  22. 22. Copyright © 2018 TIS Inc. All rights reserved. 22 Letʼs run the app まずは、動かしてみましょう! HTTPリクエストのツールをインストールしてアプリを起動 • Prepare for executing http requests • install HTTPie or Advanced REST client - CLI: HTTPie (https://httpie.org/) - GUI: Advanced REST client(Chrome Extensions) https://chrome.google.com/webstore/detail/advanced-rest- client/hgmloofddffdnphfgcellkdfbfbjeloo $brew install httpie
  23. 23. Copyright © 2018 TIS Inc. All rights reserved. 23 How to use HTTPie HTTPieを使ったHTTPリクエストの送信⽅法 • CLI: HTTPie $http POST localhost:5000/events/RHCP tickets:=10 HTTP/1.1 201 Created Content-Length: 28 Content-Type: application/json Date: Sat, 10 Mar 2018 09:27:25 GMT Server: GoTicks.com REST API { "name": "RHCP", "tickets": 10 }
  24. 24. Copyright © 2018 TIS Inc. All rights reserved. 24 How to use REST client Advanced REST clientを使ったリクエストの送信⽅法 • GUI: Advanced REST client(Chrome Extensions) (1) (2) (3) (4) (8) http://localhost:5000/events/RHCP (5) (6) (7) {"tickets":10}
  25. 25. Copyright © 2018 TIS Inc. All rights reserved. 25 How to send 4 types of HTTP requests 4つのHTTPリクエストの送信⽅法 • Create an event • Get all events • Buy tickets • Cancel an event $http POST localhost:5000/events/RHCP tickets:=10 $http GET localhost:5000/events $http POST localhost:5000/events/RHCP/tickets tickets:=2 $http DELETE localhost:5000/events/RHCP/
  26. 26. Copyright © 2018 TIS Inc. All rights reserved. 26 イベントの作成、参照、購⼊、、、キャンセル、、、 >get all events >buy 2 “RHCP” tickets >get all events >buy 8 “RHCP” tickets >buy 2 “RHCP” tickets > create “RHCP” event with 10 tickets > create “ScalaMatsuri” event with 20 tickets > cancel “ScalaMatsuri” > get all events Letʼs run the app
  27. 27. Copyright © 2018 TIS Inc. All rights reserved. Chapter 2. Up and running 27 •Fetching a project template •Building a minimal Akka app for the cloud •Deploying to Heroku 第2章 最⼩のAkkaアプリケーション • 最⼩のAkkaアプリケーションをクラウドに構築
  28. 28. Copyright © 2018 TIS Inc. All rights reserved. 28 Fetching a project template for workshop ワークショップ⽤ブランチの取得 $ git checkout matsuri
  29. 29. Copyright © 2018 TIS Inc. All rights reserved. ActorSystem “go-ticks” 29 The structure of the application アプリケーションの構造 Main HTTP Server HTTP Route RestApi Actor BoxOffice Actor TicketSeller run new create create create
  30. 30. Copyright © 2018 TIS Inc. All rights reserved. 30 The structure of the Actors アクターの構造  チケット売り場とチケット販売員 RHCP Scala Matsuri boxOffice create Add/Buy/Cancel/… Actor BoxOffice Actor TicketSeller
  31. 31. Copyright © 2018 TIS Inc. All rights reserved. Exercise 0. Create ActorSystem 31 演習0.アクターシステムの⽣成
  32. 32. Copyright © 2018 TIS Inc. All rights reserved. ActorSystem “go-ticks” 32 Create ActorSystem アクターシステムの⽣成 Main HTTP Server HTTP Route RestApi Actor BoxOffice Actor TicketSeller run new create create create
  33. 33. Copyright © 2018 TIS Inc. All rights reserved. 33 Create “go-ticks” ActorSystem ActorSystem「go-ticks」の⽣成 0.0.[Main] create ActorSystem Run the App implicit val system = ActorSystem(“go-ticks”) $ sbt run ... [info] Running com.goticks.Main INFO [Slf4jLogger]: Slf4jLogger started INFO [go-ticks]: RestApi bound to /0:0:0:0:0:0:0:0:5000 INFO [go-ticks]: Success to bind to 0.0.0.0:5000
  34. 34. Copyright © 2018 TIS Inc. All rights reserved. Exercise 1. Create an event 34 演習1.イベントの作成
  35. 35. Copyright © 2018 TIS Inc. All rights reserved. 35 HTTP Route RestApi Actor BoxOffice Actor TicketSeller CreateEvent create EventCreated EventExists POST /events/RHCP Created 201 BadRequest 400 Add イベントを作成するフロー The flow of creating an event
  36. 36. Copyright © 2018 TIS Inc. All rights reserved. 36 The flow of creating an event: implement points 実装するところ Actorの⽣成とメッセージ送信(Add/ EventCreated) HTTP Route RestApi Actor BoxOffice Actor TicketSeller CreateEvent create AddEventCreated EventExists POST /events/RHCP Created 201 BadRequest 400
  37. 37. Copyright © 2018 TIS Inc. All rights reserved. 37 Exercise 1: Define and create Actors and send messages 演習1:TicketSellerアクターの⽣成、Addメッセージ の送信、EventCreatedメッセージの返信 • Create TicketSeller actor 1.1.[TicketSeller] define actor factory method 1.2.[BoxOffice ] create TicketSeller actor • Send Add message from BoxOffice to TicketSeller 1.3.[TicketSeller] define message protocol 1.4.[TicketSeller] behavior when receive messages 1.5.[BoxOffice ] send Add message • Return EventCreated message from BoxOffice to RestApi 1.6.[BoxOffice ] return EventCreated message
  38. 38. Copyright © 2018 TIS Inc. All rights reserved. 38 Exercise 1: Run the app イベント作成の動作確認 Run the app $cd akka-in-action/chapter-up-and-running/ $sbt run ... INFO [Slf4jLogger]: Slf4jLogger started INFO [go-ticks]: RestApi bound to /0:0:0:0:0:0:0:0:5000 INFO [go-ticks]: Success to bind to 0.0.0.0:5000 Send a HTTP request $http POST localhost:5000/events/RHCP tickets:=10 HTTP/1.1 201 Created ... { "name": "RHCP", "tickets": 10 }
  39. 39. Copyright © 2018 TIS Inc. All rights reserved. 39 Create TicketSeller actor TicketSellerアクターの⽣成 1.1.[TicketSeller] define actor factory method 1.2.[BoxOffice ] create TicketSeller actor object TicketSeller { def props(event: String) = Props(new TicketSeller(event)) } class BoxOffice(implicit timeout: Timeout) extends Actor { ... def createTicketSeller(name: String) = context.actorOf(TicketSeller.props(name), name) def receive = { case CreateEvent(name, tickets) => def create() = { val eventTickets = createTicketSeller(name) ... } context.child(name).fold(create())(_ => sender() ! EventExists) } BoxOffice TicketSeller create
  40. 40. Copyright © 2018 TIS Inc. All rights reserved. 40 Send Add message from BoxOffice to TicketSeller Addメッセージの送信(BoxOffice->TicketSeller) 1.3.[TicketSeller] define message protocol 1.4.[TicketSeller] behavior when receive messages 1.5.[BoxOffice ] send Add message object TicketSeller { case class Add(tickets: Vector[Ticket]) } class BoxOffice(implicit timeout: Timeout) extends Actor { ... def receive = { case CreateEvent(name, tickets) => def create() = { ... eventTickets ! TicketSeller.Add(newTickets) } context.child(name).fold(create())(_ => sender() ! EventExists) class TicketSeller(event: String) extends Actor { import TicketSeller._ var tickets = Vector.empty[Ticket] def receive = { case Add(newTickets) => tickets = tickets ++ newTickets } BoxOffice TicketSeller Add
  41. 41. Copyright © 2018 TIS Inc. All rights reserved. 41 Return EventCreated message from BoxOffice to RestApi EventCreatedメッセージの返信(RestApi<-BoxOffice) 1.6.[BoxOffice ] return EventCreated message class BoxOffice(implicit timeout: Timeout) extends Actor { ... def receive = { case CreateEvent(name, tickets) => def create() = { ... eventTickets ! TicketSeller.Add(newTickets) sender() ! EventCreated(Event(name, tickets)) } context.child(name).fold(create())(_ => sender() ! EventExists) } RestApi BoxOffice EventCreated
  42. 42. Copyright © 2018 TIS Inc. All rights reserved. 42 Exercise 1: learned アクターの⽣成、メッセージ送信、メッセージプロトコ ルの定義、メッセージを受信したときのふるまい • create Actor • send messages • behavior when receive messages • define message protocol context.actorOf(TicketSeller.props(name), name) eventTickets ! TicketSeller.Add(newTickets) object TicketSeller { case class Add(tickets: Vector[Ticket]) } class BoxOffice(implicit timeout: Timeout) extends Actor { def receive = { case Add(newTickets) => ... object TicketSeller { def props(event: String) = Props(new TicketSeller(event)) }
  43. 43. Copyright © 2018 TIS Inc. All rights reserved. Exercise 2. Buy tickets 演習2.チケットの購⼊
  44. 44. Copyright © 2018 TIS Inc. All rights reserved. 44 The flow of buying tickets チケットを購⼊するフロー GetTicketsPOST /events/RHCP/tickets Created 201 NotFound 404 HTTP Route RestApi Actor BoxOffice Actor TicketSeller Buy Tickets
  45. 45. Copyright © 2018 TIS Inc. All rights reserved. 45 GetTickets Buy Tickets POST /events/RHCP/tickets Created 201 NotFound 404 HTTP Route RestApi Actor BoxOffice Actor TicketSeller 実装するところ メッセージ送信(Buy/ Tickets) The flow of buying tickets: implement points
  46. 46. Copyright © 2018 TIS Inc. All rights reserved. 46 Exercise 2: Send Buy message and return Tickets message 演習2:Buyメッセージを送信して、Ticketsメッセー ジを返信する • Send Buy message from BoxOffice to TicketSeller 2.1.[TicketSeller] define message protocol 2.2.[TicketSeller] behavior when receive messages - return Tickets message 2.3.[BoxOffice ] forward Buy message
  47. 47. Copyright © 2018 TIS Inc. All rights reserved. 47 チケット購⼊の動作確認 $sbt run $http POST localhost:5000/events/RHCP tickets:=10 ... $http POST localhost:5000/events/RHCP/tickets tickets:=2 HTTP/1.1 201 Created ... { "entries": [ { "id": 1 }, { "id": 2 } ], "event": "RHCP" } Exercise 2: Run the app Run the app Send a HTTP request
  48. 48. Copyright © 2018 TIS Inc. All rights reserved. 48 Send Buy message from BoxOffice to TicketSeller 送信元アクターに直接返信させるためforwardする 2.1.[TicketSeller] define message protocol 2.2.[TicketSeller] behavior when receive messages - return Tickets message 2.3.[BoxOffice ] forward Buy message object TicketSeller { case class Buy(tickets: Int) case class Tickets(event: String, entries: Vector[Ticket] = Vector.empty[Ticket]) class TicketSeller(event: String) extends Actor { def receive = { case Buy(nrOfTickets) => val entries = tickets.take(nrOfTickets) if(entries.size >= nrOfTickets) { sender() ! Tickets(event, entries) tickets = tickets.drop(nrOfTickets) } else sender() ! Tickets(event) def receive = { case GetTickets(event, tickets) => ... def buy(child: ActorRef) = child.forward(TicketSeller.Buy(tickets)) BoxOffice TicketSeller Buy BoxOffice Tickets
  49. 49. Copyright © 2018 TIS Inc. All rights reserved. 49 Exercise 2: learned メッセージの転送 • forward message child.forward(TicketSeller.Buy(tickets))
  50. 50. Copyright © 2018 TIS Inc. All rights reserved. Exercise 3. Get all events 50 演習3.イベント⼀覧の取得
  51. 51. Copyright © 2018 TIS Inc. All rights reserved. 51 The flow of getting all events イベント⼀覧を取得するフロー GetEventsGET /events/ OK 200 Events HTTP Route RestApi Actor BoxOffice Actor TicketSeller GetEvent None GetEvent Event Events
  52. 52. Copyright © 2018 TIS Inc. All rights reserved. 52 GetEvents GetEvent Event GET /events/ OK 200 Events GetEvent None Events HTTP Route RestApi Actor BoxOffice Actor TicketSeller The flow of getting all events: implement points 実装するところ メッセージ送信(GetEvent/ None/ Event/ Events)
  53. 53. Copyright © 2018 TIS Inc. All rights reserved. 53 Exercise 3: Send GetEvent message and return Event message • Return Event 3.1.[TicketSeller] defines message protocol 3.2.[TicketSeller] behavior when receive messages - return Event message • Send GetEvent message from BoxOffice to self 3.3.[BoxOffice ] sends GetEvent message to self • Define behavior when receive GetEvent message 3.4.[BoxOffice ] doesn’t find a child actor: - return None message 3.5.[BoxOffice ] finds a child actor: - forward GetEvent message • Return Events message 3.6.[BoxOffice ] returns Events message to sender 演習3:GetEventメッセージを送信して、Eventメッ セージを返信する
  54. 54. Copyright © 2018 TIS Inc. All rights reserved. 54 Exercise 3: Run the app チケット⼀覧取得の動作確認 $sbt run $http POST localhost:5000/events/RHCP tickets:=10 ... $http POST localhost:5000/events/RHCP/tickets tickets:=2 ... $http GET localhost:5000/events/ HTTP/1.1 200 OK ... { "events": [ { "name": "RHCP", "tickets": 8 } ] } Run the app Send a HTTP request
  55. 55. Copyright © 2018 TIS Inc. All rights reserved. 55 Return Event 3.1.[TicketSeller] defines message protocol 3.2.[TicketSeller] behavior when receive messages - return Event message class TicketSeller(event: String) extends Actor { def receive = { ... case GetEvent => sender() ! Some(BoxOffice.Event(event, tickets.size)) object TicketSeller { case object GetEvent } GetEventメッセージを受信したら、Eventメッセージ を返す BoxOffice TicketSeller Event
  56. 56. Copyright © 2018 TIS Inc. All rights reserved. 56 Send GetEvent message from BoxOffice to self GetEventメッセージを⾃⾝(self)に送信する 3.3.[BoxOffice ] sends GetEvent message to self class BoxOffice(implicit timeout: Timeout) extends Actor { ... def receive = { ... case GetEvents => import akka.pattern.ask def getEvents = context.children.map { child => self.ask(GetEvent(child.path.name)).mapTo[Option[Event]] } BoxOffice GetEvent
  57. 57. Copyright © 2018 TIS Inc. All rights reserved. 57 Define behavior when receive GetEvent message GetEventメッセージを受信したときのふるまい 3.4.[BoxOffice ] doesn’t find a child actor: - return None message 3.5.[BoxOffice ] finds a child actor: - forward GetEvent message class BoxOffice(implicit timeout: Timeout) extends Actor { ... def receive = { ... case GetEvent(event) => def notFound() = sender() ! None def getEvent(child: ActorRef) = child forward TicketSeller.GetEvent context.child(event).fold(notFound())(getEvent) ... BoxOffice TicketSeller GetEvent None
  58. 58. Copyright © 2018 TIS Inc. All rights reserved. 58 Return Events message pipeを使って、処理完了時にFuture内の値(Events) を送信元に返信する 3.6.[BoxOffice ] returns Events message to sender class BoxOffice(implicit timeout: Timeout) extends Actor { ... def receive = { ... case GetEvents => import akka.pattern.ask import akka.pattern.pipe def getEvents = context.children.map { child => self.ask(GetEvent(child.path.name)).mapTo[Option[Event]] } def convertToEvents(f: Future[Iterable[Option[Event]]]) = f.map(_.flatten).map(l=> Events(l.toVector)) pipe(convertToEvents(Future.sequence(getEvents))) to sender() ... RestApi BoxOffice Events
  59. 59. Copyright © 2018 TIS Inc. All rights reserved. 59 Exercise 3: learned 応答が必要なメッセージ、⾃⾝へのメッセージ送信 send message which needs a response send message to myself self.ask(GetEvent(child.path.name)).mapTo[Option[Event]] pipe(convertToEvents(Future.sequence(getEvents))) to sender() self.ask(GetEvent(child.path.name)).mapTo[Option[Event]]
  60. 60. Copyright © 2018 TIS Inc. All rights reserved. Exercise 4. Cancel an event 60 演習4.イベントのキャンセル
  61. 61. Copyright © 2018 TIS Inc. All rights reserved. 61 The flow of Canceling an event イベントをキャンセルするフロー CancelEvent Cancel Event DELETE /events/RHCP OK 200 None PoisonPill HTTP Route RestApi Actor BoxOffice Actor TicketSeller
  62. 62. Copyright © 2018 TIS Inc. All rights reserved. 62 CancelEvent Cancel Event DELETE /events/RHCP OK 200 None PoisonPill HTTP Route RestApi Actor BoxOffice Actor TicketSeller The flow of Canceling an event: implement points 実装するところ メッセージ送信(Cancel/ Event)、アクターの停⽌
  63. 63. Copyright © 2018 TIS Inc. All rights reserved. 63 Exercise 4: Send Cancel message and stop TicketSeller actor 演習4:Cancelメッセージの送信とTicketSellerアク ターの停⽌ Send Cancel message from BoxOffice to TicketSeller 4.1.[TicketSeller] define message protocol 4.2.[TicketSeller] behavior when receive messages return Event message send PoisonPill to self 4.3.[BoxOffice ] forward Cancel message
  64. 64. Copyright © 2018 TIS Inc. All rights reserved. 64 Exercise 4: Run the app $sbt run $http POST localhost:5000/events/RHCP tickets:=10 ... $http POST localhost:5000/events/RHCP/tickets tickets:=2 ... $http GET localhost:5000/events/ ... $http DELETE localhost:5000/events/RHCP HTTP/1.1 200 OK ... { "name": "RHCP", "tickets": 8 } Run the app Send a HTTP request イベントキャンセルの動作確認
  65. 65. Copyright © 2018 TIS Inc. All rights reserved. 65 Send Cancel message from BoxOffice to TicketSeller PoisonPillメッセージを送信してアクターを停⽌する 4.1.[TicketSeller] define message protocol 4.2.[TicketSeller] behavior when receive messages - return Event message - send PoisonPill to self 4.3.[BoxOffice ] forward Cancel message object TicketSeller { case object Cancel } class TicketSeller(event: String) extends Actor { def receive = LoggingReceive { case Cancel => sender() ! Some(BoxOffice.Event(event, tickets.size)) self ! PoisonPill class BoxOffice(implicit timeout: Timeout) extends Actor with ActorLogging { def receive = LoggingReceive { case CancelEvent(event) => def notFound() = sender() ! None def cancelEvent(child: ActorRef) = child forward TicketSeller.Cancel context.child(event).fold(notFound())(cancelEvent)
  66. 66. Copyright © 2018 TIS Inc. All rights reserved. 66 RestApi RestRoutes trait trait RestRoutes extends BoxOfficeApi with EventMarshalling { import StatusCodes._ def routes: Route = eventsRoute ~ eventRoute ~ ticketsRoute def eventsRoute = ... def eventRoute = pathPrefix("events" / Segment) { event => pathEndOrSingleSlash { post { ... } ~ get { ... } ~ delete { // DELETE /events/:event onSuccess(cancelEvent(event)) { _.fold(complete(NotFound))(e => complete(OK, e)) } } } } RestRoutesトレイト
  67. 67. Copyright © 2018 TIS Inc. All rights reserved. 67 RestApi BoxOfficeApi trait trait BoxOfficeApi { import BoxOffice._ def createBoxOffice(): ActorRef implicit def executionContext: ExecutionContext implicit def requestTimeout: Timeout lazy val boxOffice = createBoxOffice() ... def cancelEvent(event: String) = boxOffice.ask(CancelEvent(event)) .mapTo[Option[Event]] ... } BoxOfficeApiトレイト
  68. 68. Copyright © 2018 TIS Inc. All rights reserved. 68 Exercise 4: learned アクターの停⽌、RestAPI stop Actor Rest API class TicketSeller(event: String) extends Actor { def receive = LoggingReceive { case Cancel => sender() ! Some(BoxOffice.Event(event, tickets.size)) self ! PoisonPill def routes: Route = eventsRoute ~ eventRoute ~ ticketsRoute def eventRoute = pathPrefix("events" / Segment) { event => pathEndOrSingleSlash { delete { // DELETE /events/:event }
  69. 69. Copyright © 2018 TIS Inc. All rights reserved. Chapter 2. Up and running 69 •Fetching a project template •Building a minimal Akka app for the cloud •Deploying to Heroku 第2章 最⼩のAkkaアプリケーション • Herokuへのデプロイ
  70. 70. Copyright © 2018 TIS Inc. All rights reserved. 70 Into the cloud Create the app on Heroku $cd .. $heroku login $heroku create Creating app... done, ⬢ vast-harbor-91925 https://vast-harbor-91925.herokuapp.com/ | https://git.heroku.com/vast-harbor-91925.git Heroku上にアプリケーションを作成する install heroku CLI $brew install heroku
  71. 71. Copyright © 2018 TIS Inc. All rights reserved. 71 Into the cloud Push the code to Heroku $git subtree push --prefix chapter-up-and-running heroku master ----> Scala app detected -----> Installing OpenJDK 1.8... done .... // 依存するライブラリが解決され、ダウンロードされる .... -----> Compressing... Done: 68.8M -----> Launching... Released v1 https://damp-bayou-9575.herokuapp.com/ deployed to Heroku To git@heroku.com:damp-bayou-9575.git * [new branch] master -> master $ http POST damp-bayou-9575.herokuapp.com/events/RHCP tickets:=250 $ http POST damp-bayou-9575.herokuapp.com/events/RHCP/tickets tickets:=4 Test Heroku instance with HTTPie ソースコードをHerokuにプッシュして、動作確認
  72. 72. Copyright © 2018 TIS Inc. All rights reserved. Conclusion 72 まとめ
  73. 73. Copyright © 2018 TIS Inc. All rights reserved. 73 Conclusion Done • built a minimal set of REST services using Akka Next Exercises • lost data if the application restarts • neither scale up nor out • doesn’t know how to test • the whole system is down when a server fails Akkaを使って⼩さなRESTサービスを作りました。 しかし、再起動すると?スケールアウトは?テストは?障害起きると...
  74. 74. Copyright © 2018 TIS Inc. All rights reserved. Reference materials 74 Amazonとかにレビューを書いてくださる⽅に『Akka実 践バイブル』をプレゼント!! • メニーコア時代のパラダイム リアクティブシステムを知ろう(ThinkIT)
  75. 75. THANK YOU

×