【问题标题】:Java - Play2 Are Actors required for WebSockets implementation?Java - Play2 WebSockets 实现是否需要 Actor?
【发布时间】:2016-01-02 09:43:59
【问题描述】:

我正在尝试使用 Play2 和 Java 实现基于 WebSockets 的解决方案。目前我没有使用Actor Model 进行并发管理。相反,它只是handling the WebSockets using callbacks

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

我的猜测是带有简单回调的 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 with Java & WebSockets 一致的文档,该文档建议强制使用 Actor 来保持与所有连接的活动客户端的一致通信。

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

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

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

【问题讨论】:

  • 你有什么错误?
  • @nikpon 没有错误,来自服务器的消息只反映在 1 个浏览器会话中 - 触发了请求而不是任何其他连接的客户端会话
  • 您是如何获得浏览器会话的?
  • @nikpon 使用 2 个具有有效用户凭据的浏览器登录到系统。请参考编辑。
  • 为了更清晰的实验,最好使用同一制造商的浏览器,例如 FF,例如

标签: java playframework websocket playframework-2.0


【解决方案1】:

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

// 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);
                }
            });
        }
    };
}

您还可以使用actors来模拟这个问题:让actor负责跟踪连接并处理新的套接字连接/关闭。

如果你想使用 Akka,有 some activator templates 帮助你开始。

【讨论】:

    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 2012-01-06
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多