How to stop an akka thread on shutdown

2019-04-10 10:28发布

问题:

I am currently using the play framework (version 2.0.1). My application is required to listen to udp broadcast messages. So I need a new thread to monitor the socket and receive the required bytes. After looking into the play framework it seems the Akka system is used to handle threads/jobs. So I have implemented a new background akka task that reads my sockets. See below. Everything is working how I expected and I am able to receive the data I want in the background task. The problem I have is when I shutdown the server. In development pressing Control D. It says the message "[info] play - Shutdown application default Akka system." but then hangs and never shuts down my background thread.

public running = false;
public void onReceive(Object message) {
    if (message instanceof SystemConfiguration) {
        try {
            InetAddress group = InetAddress.getByName("222.1.1.1");
            MulticastSocket socket = new MulticastSocket(54321);
            socket.joinGroup(group);
            running = true;

            while (running) {
                Logger.info("MultiCastController - waiting to receive message");
                byte[] buf = new byte[1000];
                DatagramPacket recv = new DatagramPacket(buf, buf.length);
                socket.setSoTimeout(30000);
                try {
                    socket.receive(recv);
                    String msgString = new String(recv.getData()).trim();
                    Logger.info("retreived: " + msgString);
                } catch (SocketTimeoutException e) {
                    Logger.info("MultiCastController - timed out"
                            + recv.getData().toString());
                }
            }
        } catch (Exception ex) {
            Logger.info("Errror message caught: " + ex.toString());
        }
    } else {
        Logger.info("Error starting multicast receiver incorrect value passed: ");
    }
}

I have tried to override post stop but it never seems to be called. I have also tried akka.system().isTerminated() but it didnt work.

@Override
public void postStop()
{
    Logger.info("MultiCastController - postStop() - stopping thread");
    running = false;
}

The other possible option I have been searching for is there any way to get the akka state? that it is shutting down so i can do something like

while(running && akka.system().alive()). I have found that if i do receive a message it crashes because the ebean server has been shut down. Can I even do a hack and check if that is alive somehow?

while(running && ebean.server.isalive())

回答1:

Create your thread as a daemon thread, then it will exist when the application exits.

Or you can register a callback to be executed when the ActorSystem shuts down:

def registerOnTermination (code: Runnable): Unit

Register a block of code (callback) to run after all actors in this actor system have been stopped.

From: http://doc.akka.io/api/akka/2.0.1/#akka.actor.ActorSystem



回答2:

You can override Global.onStop to send a stop message to your actor. If that runs too late, you can register a plug-in very early in the list to send that stop message as soon as Play starts shutting down:

import play.api.Plugin
import play.api.Application

class ShutdownObserver(app: Application) extends Plugin {

  override def onStop() {
    ... send message to your actor telling it to stop...
  }
}

And then create your conf/play.plugins file with:

1:ShutdownObserver