Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to write a TCP server which handles multiple connections.
I know the way Java does it with sockets is that it has a pool of threads, the server has a while loop waiting for connections and when 'accpets' one it 'gets' a thread from the pool to handle the request.
I was picturing something similar with actors.
class TcpServer(remote: InetSocketAddress) extends Actor {
import Tcp._
import context.system
IO(Tcp) ! Bind(self, remote)
def receive = {
case b # Bound(localAddress) =>
context.parent ! b
case CommandFailed(_: Bind) ⇒ context stop self
case c # Connected(remote, local) =>
val handler: ActorRef = context.actorOf(RoundRobinPool(5).props(Props[SimplisticHandler]), "router")
sender() ! Register(handler)
}
But obviously, that is not enough. What am i missing here?
For Akka TCP the pattern generally used is to have one actor handle the connection. Since actors get scheduled onto threads as needed by the ActorSystem's dispatcher, the pattern of getting a thread from a thread pool is provided more or less automatically by Akka (it's possible to, for instance, configure the default dispatcher to be a pool of a single thread, but that's not default and not recommended).
With that in mind, you'll want to replace the
context.actorOf(RoundRobinPool(5).props(Props[SimplisticHandler]), "router")
with
context.actorOf(Props[SimplisticHandler])
and be sure in SimplisticHandler to
context.stop.self
in response to a ConnectionClosed message.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I basically wanted to understand actor model in proper manner.
I want to understand what is akka actor, actorsystem, actormaterializer, actorreffactory and dispatcher in the below code.
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import scala.io.StdIn
object MainRunner extends App {
implicit val system = ActorSystem("mySystem")
implicit val materializer = ActorMaterializer
implicit val ec = system.dispatcher
val route =
path("hello") {
get {
complete("Congratulation , this is your response")
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
If you want to really understand Actor model, the wikipedia entry is your best bet. If you want to understand Actors in Akka, Akka documentation on it is your best bet(ActorSystem, Dispatcher are implementation detail of Akka Actor model implementation). Only after you understand that should you move to Akka-HTTP. Its based on the concept of Streams, which can be loosely defined as Lazy lists. Akka streams are "materialized" through ActorMaterializer. Happy Learning!
Is it a valid StackOverflow answer to tell people to get a book? Well, if it is, I might just have the right tip for you - you can get the first 3 chapters of Akka in Action for free from the Lightbend Website (free registration required). If I recall correctly, chapter 2 has a code snippet much like yours and explains it line by line.
I'm trying to write a TCP server using Akka and Scala, which will instantiate actors and stop the actors when a client connects and disconnects respectively. I have a TCP binding actor,
class Server extends Actor{
import Tcp._
import context.system
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 9595))
def receive = {
case Bound(localAddress) =>
println("Server Bound")
println(localAddress)
case CommandFailed(_: Bind) => context stop self
case Connected(remote, local)=>
val handler = context.system.actorOf(Props[ConnHandler])
val connection = sender()
connection ! Register(handler)
}
}
The above instantiates a TCP listener on localhost:9595 and registers handler actors to each connection.
I then have the receive def in my ConnHandler class defined as such, abbreviated with ... where the code behaves correctly.
case received => {...}
case PeerClosed => {
println("Stopping")
//Other actor stopping, cleanup.
context stop self
}
(See http://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html for the docs I used to write this - it uses more or less the same code in the PeerClosed case)
However, when I close the socket client-side, the actor remains running, and no "Stopping" message is printed.
I have no nearby configured non-Windows machines to test this on, since I believe this to do with me running on Windows because after googling around, I found a still open bug - https://github.com/akka/akka/issues/17122 - which refers to some Close events being missed on Windows-based systems.
Have I made a silly error in my code, or would this be part of the bug linked above?
Although I could write in a case for Received(data) that would close the connection, however, a disconnect caused by the network disconnecting or something would leave the server in an unrecoverable state, requiring the application to be restarted since it would leave a secondary, shared actor in a state that says the client is still connected, and thus, the server would reject further connections from that user.
Edit:
I've worked around this by adding a watchdog timer actor that has a periodic action that fires after some amount of time. The ConnHandler actor will reset the watchdog timer every time an event happens on the connection. Although not ideal, it does what I want to do.
Edit 12/9/2016:
ConnHandler will receive a PeerClosed message even when a client Unexpectedly disconnect.
I'm creating an actor system, which has a list of actors representing some kind of session state.
These session are created by a factory actor (which might, in the future, get replaced by a router, if performance requires that - this should be transparent to the rest of the system, however).
Now I want to implement an operation where I get some state information from each of my currently existing session actors.
I have no explicit session list, as I want to rely on the actor system "owning" the sessions. I tried to use the actor system to look up the current session actors. The problem is that I did not find a "get all actor refs with this naming pattern" method. I tried to use the "/" operator on the system, followed by resolveOne - but got lost in a maze of future types.
The basic idea I had was:
- Send a message to all current session actors (as given to my by my ActorSystem).
- Wait for a response from them (preferably by using just the "ask" pattern - the method calling this broadcaster request/response is just a monitoring resp. debugging method, so blocking is no probleme here.
- And then collect the responses into a result.
After a death match against Scala's type system I had to give up for now.
Is there really no way of doing something like this?
If I understand the question correctly, then I can offer up a couple of ways you can accomplish this (though there are certainly others).
Option 1
In this approach, there will be an actor that is responsible for waking up periodically and sending a request to all session actors to get their current stats. That actor will use ActorSelection with a wildcard to accomplish that goal. A rough outline if the code for this approach is as follows:
case class SessionStats(foo:Int, bar:Int)
case object GetSessionStats
class SessionActor extends Actor{
def receive = {
case GetSessionStats =>
println(s"${self.path} received a request to get stats")
sender ! SessionStats(1, 2)
}
}
case object GatherStats
class SessionStatsGatherer extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
def receive = {
case GatherStats =>
println("Waking up to gether stats")
val sel = context.system.actorSelection("/user/session*")
sel ! GetSessionStats
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
Then you could test this code with the following:
val system = ActorSystem("test")
system.actorOf(Props[SessionActor], "session-1")
system.actorOf(Props[SessionActor], "session-2")
system.actorOf(Props[SessionStatsGatherer])
Thread.sleep(10000)
system.actorOf(Props[SessionActor], "session-3")
So with this approach, as long as we use a naming convention, we can use an actor selection with a wildcard to always find all of the session actors even though they are constantly coming (starting) and going (stopping).
Option 2
A somewhat similar approach, but in this one, we use a centralized actor to spawn the session actors and act as a supervisor to them. This central actor also contains the logic to periodically poll for stats, but since it's the parent, it does not need an ActorSelection and can instead just use its children list. That would look like this:
case object SpawnSession
class SessionsManager extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
var sessionCount = 1
def receive = {
case SpawnSession =>
val session = context.actorOf(Props[SessionActor], s"session-$sessionCount")
println(s"Spawned session: ${session.path}")
sessionCount += 1
sender ! session
case GatherStats =>
println("Waking up to get session stats")
context.children foreach (_ ! GetSessionStats)
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
And could be tested as follows:
val system = ActorSystem("test")
val manager = system.actorOf(Props[SessionsManager], "manager")
manager ! SpawnSession
manager ! SpawnSession
Thread.sleep(10000)
manager ! SpawnSession
Now, these examples are extremely trivialized, but hopefully they paint a picture for how you could go about solving this issue with either ActorSelection or a management/supervision dynamic. And a bonus is that ask is not needed in either and also no blocking.
There have been many additional changes in this project, so my answer/comments have been delayed quite a bit :-/
First, the session stats gathering should not be periodical, but on request. My original idea was to "mis-use" the actor system as my map of all existing session actors, so that I would not need a supervisor actor knowing all sessions.
This goal has shown to be elusive - session actors depend on shared state, so the session creator must watch sessions anyways.
This makes Option 2 the obvious answer here - the session creator has to watch all children anyways.
The most vexing hurdle with option 1 was "how to determine when all (current) answers are there" - I wanted the statistics request to take a snapshot of all currently existing actor names, query them, ignore failures (if a session dies before it can be queried, it can be ignored here) - the statistics request is only a debugging tool, i.e. something like a "best effort".
The actor selection api tangled me up in a thicket of futures (I am a Scala/Akka newbie), so I gave up on this route.
Option 2 is therefore better suited to my needs.
I am currently evaluating javascript scripts using Rhino in a restful service. I wish for there to be an evaluation time out.
I have created a mock example actor (using scala 2.10 akka actors).
case class Evaluate(expression: String)
class RhinoActor extends Actor {
override def preStart() = { println("Start context'"); super.preStart()}
def receive = {
case Evaluate(expression) ⇒ {
Thread.sleep(100)
sender ! "complete"
}
}
override def postStop() = { println("Stop context'"); super.postStop()}
}
Now I run use this actor as follows:
def run {
val t = System.currentTimeMillis()
val system = ActorSystem("MySystem")
val actor = system.actorOf(Props[RhinoActor])
implicit val timeout = Timeout(50 milliseconds)
val future = (actor ? Evaluate("10 + 50")).mapTo[String]
val result = Try(Await.result(future, Duration.Inf))
println(System.currentTimeMillis() - t)
println(result)
actor ! PoisonPill
system.shutdown()
}
Is it wise to use the ActorSystem in a closure like this which may have simultaneous requests on it?
Should I make the ActorSystem global, and will that be ok in this context?
Is there a more appropriate alternative approach?
EDIT: I think I need to use futures directly, but I will need the preStart and postStop. Currently investigating.
EDIT: Seems you don't get those hooks with futures.
I'll try and answer some of your questions for you.
First, an ActorSystem is a very heavy weight construct. You should not create one per request that needs an actor. You should create one globally and then use that single instance to spawn your actors (and you won't need system.shutdown() anymore in run). I believe this covers your first two questions.
Your approach of using an actor to execute javascript here seems sound to me. But instead of spinning up an actor per request, you might want to pool a bunch of the RhinoActors behind a Router, with each instance having it's own rhino engine that will be setup during preStart. Doing this will eliminate per request rhino initialization costs, speeding up your js evaluations. Just make sure you size your pool appropriately. Also, you won't need to be sending PoisonPill messages per request if you adopt this approach.
You also might want to look into the non-blocking callbacks onComplete, onSuccess and onFailure as opposed to using the blocking Await. These callbacks also respect timeouts and are preferable to blocking for higher throughput. As long as whatever is way way upstream waiting for this response can handle the asynchronicity (i.e. an async capable web request), then I suggest going this route.
The last thing to keep in mind is that even though code will return to the caller after the timeout if the actor has yet to respond, the actor still goes on processing that message (performing the evaluation). It does not stop and move onto the next message just because a caller timed out. Just wanted to make that clear in case it wasn't.
EDIT
In response to your comment about stopping a long execution there are some things related to Akka to consider first. You can call stop the actor, send a Kill or a PosionPill, but none of these will stop if from processing the message that it's currently processing. They just prevent it from receiving new messages. In your case, with Rhino, if infinite script execution is a possibility, then I suggest handling this within Rhino itself. I would dig into the answers on this post (Stopping the Rhino Engine in middle of execution) and setup your Rhino engine in the actor in such a way that it will stop itself if it has been executing for too long. That failure will kick out to the supervisor (if pooled) and cause that pooled instance to be restarted which will init a new Rhino in preStart. This might be the best approach for dealing with the possibility of long running scripts.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I'm having a little problem with Scala Actors and blocking IO. I'm using an actor that itself has an anonymous actor that consumes an input stream. The problem is that this stream only reads one line and then blocks without waking up again. What confuses me is that it worked when the consumption took place in the act method (coincidence?). The application itself has some more actors and java threads doing some work.
My question is: What is the common practice to avoid such problems? Any pointers?
The code that causes this problem looks somewhat like this:
object TestActor extends Actor {
private val instream = actor {
loop {
try {
println(processInput(input.readLine)) //bufferedinputstream. blocks, no wakeup
} catch {
case e: Exception =>
println(e.toString)
}
}
}
def act(): Unit = {
react {
...
case _ => {}
}
}
}
Regards,
raichoo
The call to readLine is inside loop{} so it's going to happen over and over until it blocks.