【问题标题】:Playframework 2.3 shutdown on code changes with an Akka job runningPlayframework 2.3 在运行 Akka 作业时关闭代码更改
【发布时间】:2015-03-24 19:37:08
【问题描述】:

我有一个在后台运行的 akka 任务来监听 UDP 包。但是,当我这样做时,我对代码进行了更改,系统会重新编译,但随后会停止/挂起,我需要完全停止并重新启动(如果每次更改后都需要这样做,这需要很长时间)。当我不启动客家任务时,它工作正常。这是控制台输出:

[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Starting application default Akka system.
[info] application - Starting UDP server
[info] play - Application started (Dev)
[debug] application - Ready to receive broadcast packets!
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[success] Compiled in 6s
[info] Compiling 1 Scala source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...

--- (RELOAD) ---

[info] play - Shutdown application default Akka system.

我正在使用 IDEA 14。

这是我的全局: 公共类 Global 扩展 GlobalSettings {

@Override
public void onStart(Application app) {
    if (SensorRole.find.findRowCount() != SensorRole.RoleName.values().length) {
        for (SensorRole.RoleName roleName : SensorRole.RoleName.values()) {
            SensorRole newRole = new SensorRole();
            newRole.name = roleName.toString();
            newRole.save();
        }


    }

    ActorRef instance = Akka.system().actorOf(Props.create(UDPBroadcastServer.class), "UDPServer");
    instance.tell("Start", ActorRef.noSender());

    super.onStart(app);
}

@Override
public void onStop(Application app){
    Logger.debug("Stopping system...");
    Akka.system().shutdown();

    super.onStop(app);
}

}

和 UDPBroadcastServer:

public class UDPBroadcastServer extends UntypedActor {

    DatagramSocket socket;
    boolean stop;

    @Override
    public void postStop() throws Exception {
        super.postStop();
        stop = true;
        Logger.info("Master Killed");
    }

    @Override
    public void onReceive(Object command) throws Exception {
        Logger.info("Starting UDP server");
        stop = false;
    String action = (String) command;
    if (action.equals("Start")) {
        try {
            //Keep a socket open to listen to all the UDP trafic that is destined for this port
            socket = new DatagramSocket(8888, InetAddress.getByName("0.0.0.0"));

            socket.setBroadcast(true);

            while (!stop) {
                Logger.debug("Ready to receive broadcast packets!");

                //Receive a packet
                byte[] recvBuf = new byte[15000];
                packet = new DatagramPacket(recvBuf, recvBuf.length);
                socket.receive(packet);

                //Packet received
                Logger.debug("Discovery packet received from: " + packet.getAddress().getHostAddress());
                Logger.debug("Packet received; data: " + new String(packet.getData()));

                //See if the packet holds the right command (message)
                String message = new String(packet.getData()).trim();
                if (message.equals("DISCOVER_TEMPSERVER_REQUEST")) {
                    byte[] sendData = "DISCOVER_TEMPSERVER_RESPONSE".getBytes();

                    //Send a response
                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                    socket.send(sendPacket);

                    Logger.debug("Sent packet to: " + sendPacket.getAddress().getHostAddress());
                }
            }
        } catch (IOException ex) {
            Logger.error("Problem with UDP server:" + ex.getLocalizedMessage());
        }
    } else if (action.equals("Stop")) {
        Logger.debug("Trying to stop process!");
        stop = true;
        if(packet != null) packet = null;
        if(socket.isConnected()) socket.close();
    }
}

[编辑]: 根据推荐,我正在尝试手动停止任务。但是,我无法重新获得 ActorRef 的句柄。我正在尝试这样做:

    ActorRef test = Akka.system().actorFor("//application/user/UDPServer");
    test.tell("Stop", ActorRef.noSender());
    Logger.debug("Path: " + test.path());
    Akka.system().stop(test);

但是 Actor 的 'onReceive' 永远不会收到 'Stop'。

【问题讨论】:

  • 我猜你的演员在 socket.receive(packet) 上被屏蔽了。从文档中,您可以理解原因:This method blocks until a datagram is received.,因此您的停止标志没有意义。
  • 好的,有道理。我现在正在尝试关闭套接字,但似乎无法处理已经激活的 tsk。我使用 test.tell("Stop", ActorRef.noSender());根据上面的代码,但没有收到任何东西。也许我应该为套接字创建一个单独的线程。
  • 这可能会有所帮助:stackoverflow.com/questions/4425350/…
  • 我把套接字放在一个单独的线程中,现在 olnrecieve 可以接收调用,并关闭套接字,一切正常(我在 Play Global 的 onStop 上添加了停止。)如果你想把答案放进去,然后我会接受你指出的问题。
  • 嗨,谢谢。我将这些 cmets 复制到答案中。

标签: java playframework-2.0 akka


【解决方案1】:

我猜你的演员在socket.receive(packet) 上被屏蔽了。从文档中,您可以理解原因:This method blocks until a datagram is received,因此您的停止标志没有意义。这可能会有所帮助:How to terminate a thread blocking on socket IO operation instantly?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多