Más contenido relacionado
La actualidad más candente (20)
Similar a Akka in Action workshop #ScalaMatsuri 2018 (20)
Akka in Action workshop #ScalaMatsuri 2018
- 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. 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. Copyright © 2018 TIS Inc. All rights reserved. 3
TISカジュアルはじめました
2018.3.1
TIS casual has started!
We are hiring!
- 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. Copyright © 2018 TIS Inc. All rights reserved. 5
Material
教材は『Akka実践バイブル』
✦here
- 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. 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. Copyright © 2018 TIS Inc. All rights reserved.
Chapter 1. Introducing Akka
8
第1章 Akkaの紹介
- 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved. 12
Traditional scaling and Akka scaling
アクターと伝統的なアプローチの⽐較
• Traditional • Akka
- 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved. 16
Akka actors: ActorRef and Mailbox and Actor
ActorRefに到着したメッセージは⼀時的にメールボッ
クスに保存し到着順に処理する
- 17. Copyright © 2018 TIS Inc. All rights reserved.
Chapter 2. Up and running
17
第2章 最⼩のAkkaアプリケーション
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved. 28
Fetching a project template for workshop
ワークショップ⽤ブランチの取得
$ git checkout matsuri
- 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. 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. Copyright © 2018 TIS Inc. All rights reserved.
Exercise 0. Create ActorSystem
31
演習0.アクターシステムの⽣成
- 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. 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. Copyright © 2018 TIS Inc. All rights reserved.
Exercise 1. Create an event
34
演習1.イベントの作成
- 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. 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. 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. 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. 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. 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved.
Exercise 2. Buy tickets
演習2.チケットの購⼊
- 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. 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. 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved. 49
Exercise 2: learned
メッセージの転送
• forward message
child.forward(TicketSeller.Buy(tickets))
- 50. Copyright © 2018 TIS Inc. All rights reserved.
Exercise 3. Get all events
50
演習3.イベント⼀覧の取得
- 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. 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. 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. 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. 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. 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. 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. 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. 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. Copyright © 2018 TIS Inc. All rights reserved.
Exercise 4. Cancel an event
60
演習4.イベントのキャンセル
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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にプッシュして、動作確認
- 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. Copyright © 2018 TIS Inc. All rights reserved.
Reference materials
74
Amazonとかにレビューを書いてくださる⽅に『Akka実
践バイブル』をプレゼント!!
• メニーコア時代のパラダイム リアクティブシステムを知ろう(ThinkIT)