akka(7)Akka Remote Actor and Akka in Spray
Dispatcher is to pick up the thread to execute the message box and actor.
Router is an actor to route the message to different actors.
1. Akka System
router to jvm Akka System.
A very Simple Actor, just receive the Message and Print,
EventMessageActor.
package com.sillycat.akka.actor
import akka.actor.Actor
import com.typesafe.scalalogging.slf4j.Logging
import com.sillycat.akka.model.EventMessage
class EventMessageActor extends Actor with Logging {
logger.info("Created a EventMessage Actor")
def receive = {
case item: EventMessage => {
//handle the eventMessage
logger.debug("Logging I receive one object:" + item)
//this will send the response back
//sender ! item + " Server is running this task"
}
case item: String => {
logger.debug("Logging I receive one object:" + item)
}
case _ => logger.error("Received a message I don't understand.")
}
}
The
WatcherActor
package com.sillycat.akka.actor
import akka.actor.{ Terminated, Actor, ActorRef }
import com.typesafe.scalalogging.slf4j.Logging
class ActorWatcher(watched: ActorRef) extends Actor with Logging {
context.watch(watched)
def receive = {
case Terminated(watched) => {
logger.info("The watched actor was terminated: " + watched.toString())
context.system.shutdown()
}
case _ => logger.info("ActorWatcher got a message not intended for it!")
}
}
The configuration file about this actor with router in
localjvm.conf
akka {
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "DEBUG"
# Log the complete configuration at INFO level when the actor system is started.
# This is useful when you are uncertain of what configuration is used.
#log-config-on-start = on
actor.deployment {
/EventMessageLocalRouter {
router = round-robin
resizer {
lower-bound = 5
upper-bound = 100
}
}
}
}
Simple Application class,
EventService for Testing
package com.sillycat.akka.server
import com.sillycat.akka.actor.{ ActorWatcher, EventMessageActor }
import com.typesafe.config.ConfigFactory
import com.typesafe.scalalogging.slf4j.Logging
import akka.actor._
import akka.routing.{ FromConfig, RoundRobinRouter }
import akka.routing.Broadcast
import com.sillycat.akka.model.EventMessage
class EventService extends Logging {}
object EventService extends Logging {
//private val logger = (new EventService()).logger
logger.info("Starting EventService...")
def startOne(item: EventMessage) = {
router ! item
}
def shutdown() = {
logger.info("Broadcast PoisonPill...")
router ! Broadcast(PoisonPill)
logger.info("EventService shut down.")
}
private lazy val actorSystem = ActorSystem("EventServiceLocalSystem", ConfigFactory.load("localjvm"))
private lazy val router = actorSystem.actorOf(Props[EventMessageActor].withRouter(FromConfig()), name = "EventMessageLocalRouter")
private lazy val routerWatcher =
actorSystem.actorOf(Props(new ActorWatcher(router)), name = "EventMessageLocalRouterWatcher")
}
Testing Class based on
EventService
package com.sillycat.akka.server
import com.sillycat.akka.model.EventMessage
import org.joda.time.DateTime
import org.scalatest.BeforeAndAfter
import org.scalatest.FunSuite
class EventServiceTest extends FunSuite with BeforeAndAfter {
before {
}
after {
}
test("Testing EventService start one...") {
def item = EventMessage(1, "request1", "request2", "admin", DateTime.now())
Range(1, 10) foreach { i =>
EventService.startOne(item)
}
Thread.sleep(1000)
EventService.shutdown()
}
}
2. Remote Akka System
Users/carl/work/akka/akka/akka-samples/akka-sample-remote-scala/tutorial/index.html
Server Side EventServiceRemoteApp.
package com.sillycat.akka.server
import akka.actor.{ Props, ActorSystem }
import akka.kernel.Bootable
import com.sillycat.akka.actor.EventMessageActor
import com.typesafe.config.ConfigFactory
class EventServiceRemoteApp extends Bootable {
val system = ActorSystem("EventServiceRemoteSystem", ConfigFactory.load("remotesystem"))
def startup = {
system.actorOf(Props[EventMessageActor], name = "EventMessageRemoteActor")
}
def shutdown = {
system.shutdown()
}
}
The configuration file
common.conf
akka {
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "DEBUG"
# Log the complete configuration at INFO level when the actor system is started.
# This is useful when you are uncertain of what configuration is used.
#log-config-on-start = on
actor {
serialize-messages = on
serializers {
java = "akka.serialization.JavaSerializer"
proto = "akka.remote.serialization.ProtobufSerializer"
}
serialization-bindings {
"java.lang.String" = java
"com.sillycat.akka.model.EventMessage" = java
}
}
}
configuration file
remotesystem.conf
include "common"
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname = "10.190.191.15"
port = 2552
}
}
}
After that, we need to build the assembly jar and place the jar under
/opt/akka/deploy
The binary Akka is downloaded from
http://akka.io/downloads/.
Command to start the remote Akka system
>
bin/akka com.sillycat.akka.server.EventServiceRemoteApp
Client System
EventServiceClientApp
package com.sillycat.akka.server
import akka.actor._
import akka.routing.{ Broadcast, FromConfig }
import com.sillycat.akka.actor.{ ActorWatcher, EventMessageActor }
import com.sillycat.akka.model.EventMessage
import com.typesafe.config.ConfigFactory
import com.typesafe.scalalogging.slf4j.Logging
import org.joda.time.DateTime
object EventServiceClientApp extends App {
val system = ActorSystem("EventServiceLocalSystem", ConfigFactory.load("clientsystem"))
val clientActor = system.actorOf(Props[EventMessageActor].withRouter(FromConfig()), "EventMessageClientActor")
private lazy val routerWatcher =
system.actorOf(Props(new ActorWatcher(clientActor)), name = "EventMessageClientRouterWatcher")
Range(1, 10) foreach { i =>
def item = EventMessage(1, "request1", "request2", "admin", DateTime.now())
clientActor ! "fire works."
clientActor ! item
}
Thread.sleep(5000)
clientActor ! Broadcast(PoisonPill)
system.shutdown()
}
The Client Conf,
clientsystem.conf
include "common"
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
}
akka {
actor.deployment {
/EventMessageClientActor {
remote = "akka.tcp://[email protected]:2552/user/EventMessageRemoteActor"
router = round-robin
resizer {
lower-bound = 10
upper-bound = 100
}
}
}
}
Directly run the command in project to testing.
>
sbt "run com.sillycat.akka.server.EventServiceClientApp"
3. Akka with Spray
Build the actor in app when start the spray HTTP server
system.actorOf(Props[AttributeDBImportActor].withRouter(FromConfig()), name = "AttributeDBImportRouter")
Conf
akka {
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "ERROR"
# Log the complete configuration at INFO level when the actor system is started.
# This is useful when you are uncertain of what configuration is used.
#log-config-on-start = on
actor.deployment {
/AttributeDBImportRouter {
router = round-robin
resizer {
lower-bound = 8
upper-bound = 40
}
}
}
In the http service class, select the Actor from the Akka system
implicit val attributeActorRouter = actorRefFactory.actorSelection("/user/AttributeDBImportRouter") //actor name
4. Cluster Akka System
todo...
Users/carl/work/akka/akka/akka-samples/akka-sample-cluster-scala/tutorial/index.html
References:
old blog