为什么使用AWS ELB时,grails的websockets连接失败,但仍能继续接收已在浏览器中订阅的消息?



使用Grails 2.5.5与spring-websockets插件1.3.1和tomcat 8.0.37。

使用AWS弹性负载均衡器时,在浏览器中加载应用程序时,Javascript控制台中显示以下错误

WebSocket connection to 'ws://...s.com/Application/stomp/059/uyqk9cdn/websocket' failed: Error during WebSocket handshake: Unexpected response code: 400

研究发现ELB不支持websockets和ELB内的代理,可能需要第三方负载平衡器或使用新的应用程序负载平衡器(应用程序不在VPC中,因此这不是一个简单的解决方案)。

然而,在错误之后,收到以下日志记录:

Web Socket Opened... 
>>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000
<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:admin
connected to server undefined
>>> SUBSCRIBE
id:sub-0
destination:/topic/someTopic

消息然后被客户端接收,当它们被广播时

<<< MESSAGE
destination:/topic/someTopic
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:xb71g__u-16
content-length:89
启动websocket连接的代码为
<r:require module="spring-websocket"/>
    <r:script>
        var socket = new SockJS("${createLink(uri: '/stomp')}");
        var client = Stomp.over(socket);
        client.connect({}, function () {
            var topic = "/topic/digTicketUpdated";
            console.log("Subscribing to -> " + topic);
            client.subscribe(topic, function (message) {
                console.log("Push Message Received From Server");
                updateStatus(message.body);
            });
        });
    </r:script>

摘自grails-spring-websocket github页面。

是否有可能弄清楚,如果这是回退,踢在websocket实际工作或其他一些情况。总结:

    websocket是否退回到另一个协议?
  1. 有没有办法摆脱400的错误?

感谢评论中的建议,发现在抛出"Unexpected response code: 400"之后,SockJS试图使用长POST XHR请求来模拟web套接字,并且它工作了。这可以在Chrome开发者工具的网络选项卡中查看为"xhr_streaming"。

为了防止在开发控制台中显示400错误,实现了一个可配置的开关,以便在知道不支持web套接字连接时(例如在AWS ELB上)不会尝试web套接字连接。这是通过在实例化SockJS时从允许的协议中删除"websocket"来实现的:

var allowedProtocols = ['xdr-streaming', 'xhr-streaming', 'iframe-eventsource', 'iframe-htmlfile', 'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling']
var socket = new SockJS(uri, {}, {protocols_whitelist : allowedProtocols});
var client = Stomp.over(socket);

最新更新