Java - Play2 WebSockets 实现需要 Actors 吗?

Java - Play2 Are Actors required for WebSockets implementation?

我正在尝试使用 Play2 和 Java 实现基于 WebSockets 的解决方案。目前我没有使用 Actor Model for concurrency management. Instead, it's just handling the WebSockets using callbacks.

问题是服务器无法 'broadcast' 将消息发送给多个客户端。例如,我需要所有活动的浏览器会话在通过客户端触发一个动作后接收到一个简单的通知。相反,我只能为单个客户端会话模拟这一点。实际上,它只是一个常规的 Ajax request/response 场景。

我的猜测是带有简单回调的 Play2 和 Java 的 WebSockets 解决方案无法将消息广播到所有连接的客户端浏览器。

回调服务器代码

public static WebSocket<String> heartUpdate() {
        return new WebSocket<String>() {
            public void onReady(final WebSocket.In<String> in,
                    WebSocket.Out<String> out) {
                in.onMessage(new Callback<String>() {
                    @Override
                    public void invoke(String event) throws Throwable {
                        Product product = Product.find.byId(Long.decode(event));
                        // Other business stuff
                        out.write(entity.id + " " + decimalValue);
                    }
                });
                in.onClose(new Callback0() {
                    @Override
                    public void invoke() throws Throwable {

                    }
                });
                out.write(DELIM_USERID_REP);
            }
        };
    }

路由条目

GET /repsocket   controllers.Application.heartUpdate

客户端

<script>
    // Onto the WebSockets now
    var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
    var socket = new WS("@routes.Application.heartUpdate.webSocketURL(request)");

    var receiveEvent = function(event) {
        alert(event.data);
        // Notification badge visible with a common text
        $('#notify').text(event.data);
        $('#notify').addClass('visible');
    }
        $('#heart').click(function(e) {
            e.preventDefault();
            socket.send(@product.id);
        });
    socket.onmessage = receiveEvent;
    </script>

在上述情况下,触发客户端的操作是成功从服务器接收消息的客户端,而任何其他浏览器会话都没有。

我没能找到任何与 Play2 和 Java 和 WebSockets 一致的文档,这些文档建议强制使用 Actors 来与所有连接的活动客户端保持一致的通信。

问题: Play2 中具有 Java 的 WebSockets 是否应该使用 Actor 模型实现以将消息广播到所有活动的客户端会话?

编辑: 下面的屏幕截图反映了我使用 2 个有效用户凭据登录到的浏览器的 2 种状态。

理想情况下,来自服务器的 WebSockets 响应应该在两个浏览器上创建相同的通知标志。

查看您发布的代码,问题似乎在于您没有保存对每个连接的引用,因此您可以稍后广播消息。像这样:

// Just an example: does not deal with concurrency problems
private static final Set<WebSocket.Out<String>> SOCKETS = new HashSet<>();

public static WebSocket<String> heartUpdate() {
    return new WebSocket<String>() {
        public void onReady(final WebSocket.In<String> in,
                    final WebSocket.Out<String> out) {
            SOCKETS.add(out);
            in.onMessage(new Callback<String>() {
                @Override
                public void invoke(String event) throws Throwable {
                    for(WebSocket.Out<String> s: SOCKETS) {
                        s.write("SOME MESSAGE");    
                    }
                }
            });
            in.onClose(new Callback0() {
                @Override
                public void invoke() throws Throwable {
                    SOCKETS.remove(out);
                }
            });
        }
    };
}

您还可以使用参与者来模拟此问题:让参与者负责跟踪连接并处理新套接字connection/close。

如果您想使用 Akka,some activator templates 可以帮助您入门。