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

时间:2016-09-12 20:42:36

标签: amazon-web-services grails stomp spring-websocket sockjs

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

使用AWS Elastic Load Balancer时,在浏览器中加载应用程序时,Javascript控制台中会显示以下错误

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

从研究中发现,ELB不支持ELB中的websockets和代理,第三方负载均衡器或可能使用新的Application Load Balancer(应用程序不在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 page

是否有可能弄清楚这是否是已经启动的后备,websocket实际工作或其他情况。总结一下:

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

1 个答案:

答案 0 :(得分:0)

感谢评论中的建议,发现在抛出“意外响应代码:400”之后,SockJS尝试使用长POST XHR请求来模拟Web套接字并且它有效。这在Chrome开发者工具的“网络”标签中可以看作“xhr_streaming”。

为了防止在开发控制台中显示400错误,实现了可配置的交换机,因此当知道不支持Web套接字连接时(例如在AWS ELB上),不会尝试使用Web套接字连接。这是通过从允许的协议when instantiating 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);