Sunday, April 1, 2012

Leave it crash, akka will restart it for you !!!

Akka is an awesome tool, even using default configuration, you do not have anymore to worry about failure management and recovery details. I've been bluffed to discover that my new monitoring system prototype (akka/scala based) was able to recovery by itself from errors, while I didn't yet implement such features !!

So In order to illustrate this feature, I've written a simple example that illustrates this behavior. The RobustActor actor keeps a ssh connection to a remote system (using janalyse-ssh scala ssh api), and execute/print every 5s the "date" command :
package dummy

import akka.actor.ActorSystem
import akka.actor.Actor
import akka.util.duration._
import com.typesafe.config.ConfigFactory
import akka.actor.Props

import fr.janalyse.ssh._

object DummySSH {
 def main(args:Array[String]) {
      val system=ActorSystem("DummySSHSystem",ConfigFactory.load.getConfig("dummySSH"))
      system.actorOf(
        Props(new RobustActor(system)),
        name="RobustActor")
 }
}


class RobustActor(system:ActorSystem) extends Actor {
  
  val sh = SSH(host="localhost", username="test", password=Some("testtest")).newShell
  
  override def preStart() {
    system.scheduler.schedule(1 seconds, 5 seconds, self, "doit")
  }
  
  override def postStop() {
    sh.close()
  }
    
  def receive = {
    case "doit" => print(sh execute "date")
  }
}
If we start this example code, we wait a little, we identify the sshd process that manages the established ssh connection and then we kill the sshd process, akka will intercept RobustActor internal exception and restart this actor for us !
$ sbt run
[info] Loading project definition from /home/dcr/dev-new/akka-sandbox/project
[info] Set current project to AkkaSandbox (in build file:/home/dcr/dev-new/akka-sandbox/)
[info] Compiling 1 Scala source to /home/dcr/dev-new/akka-sandbox/target/scala-2.9.1/classes...

Multiple main classes detected, select one to run:

 [1] dummy.Dummy
 [2] dummy.DummySSH

Enter number: 2

[info] Running dummy.DummySSH 
dim. avril  1 22:15:32 CEST 2012
dim. avril  1 22:15:37 CEST 2012
dim. avril  1 22:15:42 CEST 2012
dim. avril  1 22:15:47 CEST 2012
[ERROR] [04/01/2012 22:15:53.92] [DummySSHSystem-akka.actor.default-dispatcher-3] [akka://DummySSHSystem/user/RobustActor] Pipe closed
java.io.IOException: Pipe closed
 at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:244)
 at java.io.PipedInputStream.receive(PipedInputStream.java:210)
 at java.io.PipedOutputStream.write(PipedOutputStream.java:132)
 at java.io.OutputStream.write(OutputStream.java:58)
 at fr.janalyse.ssh.SSHShell$Producer.sendCommand(SSHAPI.scala:480)
 at fr.janalyse.ssh.SSHShell.sendCommand(SSHAPI.scala:475)
 at fr.janalyse.ssh.SSHShell.execute(SSHAPI.scala:448)
 at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:34)
 at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:33)
 at akka.actor.Actor$class.apply(Actor.scala:290)
 at dummy.RobustActor.apply(DummySSH.scala:21)
 at akka.actor.ActorCell.invoke(ActorCell.scala:617)
 at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:179)
 at akka.dispatch.Mailbox.run(Mailbox.scala:161)
 at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:505)
 at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259)
 at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:997)
 at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1495)
 at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

dim. avril  1 22:15:54 CEST 2012
dim. avril  1 22:15:58 CEST 2012


To identify the process which manages our example ssh connection, just use the following commands, list all sshd processes which belongs to test user, then take the process that do not use your current test shell session.
test@lanfeust ~ $ ps -ef | grep "^test"
test      8824  8815  0 11:20 ?        00:00:00 sshd: test@pts/7 
test      8825  8824  0 11:20 pts/7    00:00:00 -bash
test     32468 32458  0 22:15 ?        00:00:00 sshd: test@pts/8 
test     32469 32468  0 22:15 pts/8    00:00:00 -bash
test     32474  8825  0 22:15 pts/7    00:00:00 ps -ef
test     32475  8825  0 22:15 pts/7    00:00:00 grep --colour=auto ^test
test@lanfeust ~ $ tty
/dev/pts/7
test@lanfeust ~ $ kill -9 32468
test@lanfeust ~ $ 

This example source code is available here : akka-sandbox

1 comment:

  1. It's very great to see your post!I like it .I'm looking forward to you in the next
    post.Thank you .There is a dell recovery software to you.

    ReplyDelete