2012-10-23 12 views
5

最新のChromeブラウザでは、sockjsクライアントを使用して、haproxyの後ろにあるバックエンドサーバーと通信しようとしています。私のローカルホストでは(haproxyが中央にない)、これは正常に動作しています - クライアントはwebsocketプロトコルを使用してメッセージを接続、送受信できます。例えば:私はHAProxyと、サーバーにデプロイするとWebSocketハンドシェイクがHAProxyでハングアップする

conn.onopen = function() { 
    if (conn.readyState === SockJS.OPEN) { 
     conn.send("hello server"); 
     console.log("msg sent"); 
    } 
}; 

は、奇妙なことがsockjsが(「送信済みボックス」は、コンソールログに表示されconn.readyState === SockJS.OPEN中として)、しかし、websocketハンドシェイク接続が開いていると考えていることが起こります単純にハングし、msgはサーバーによって受信されません。以下は、私がhaproxyログに見えるものです:私シャットダウンhaproxyの背後にあるバックエンドサーバ2番目のログのMSG のみ表示されていることを

Oct 23 09:08:25 localhost.localdomain haproxy[14121]: 129.xx.xxx.105:55000 [23/Oct/2012:09:08:24.459] public www/content 777/0/0/1/778 200 375 - - ---- 3/3/0/1/0 0/0 "GET /sockjs/info HTTP/1.1" 
Oct 23 09:10:54 localhost.localdomain haproxy[14121]: 129.xx.xxx.105:55015 [23/Oct/2012:09:08:25.398] public www/content 0/0/0/1/149017 101 147 - - CD-- 4/4/0/0/0 0/0 "GET /sockjs/478/kyi342s8/websocket HTTP/1.1" 

注意してください。シャットダウンする前に、ログにエラーはありませんが、websocketハンドシェイクは完了せず、サーバはmsgを受信しません。 Chromeの開発ツールを使用して

は、ネットワーク]タブで、私は、以下を参照してください。

Request URL:ws://www.mysite.com/sockjs/478/kyi342s8/websocket 
Request Method:GET 
Status Code:101 Switching Protocols 

Request Headers 
Connection:Upgrade 
Host:www.mysite.com 
Origin:http://www.mysite.com 
Sec-WebSocket-Extensions:x-webkit-deflate-frame 
Sec-WebSocket-Key:TFEIKYhlqWWBZKlXzXAuWQ== 
Sec-WebSocket-Version:13 
Upgrade:websocket 
(Key3):00:00:00:00:00:00:00:00 

Response Headers 
Connection:Upgrade 
Sec-WebSocket-Accept:D+s3va02KH6QTso24ywcdxcfDgM= 
Upgrade:websocket 
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 

そして「種類」とwebsocketオブジェクトショー「保留」の「時間の待ち時間」の両方のネットワーク]タブの下で開発者ツール。

最後に、これは私のhaproxy設定(バージョン1.4.22)である:なぜこれが起こっている

global 
     log 127.0.0.1 local1 info 
     log 127.0.0.1 local1 notice 
     #log loghost local0 info 
     maxconn 4096 
     chroot /usr/share/haproxy 
     uid 99 
     gid 99 
     daemon 
     #debug 
     #quiet 

defaults 
     log    global 
     mode   http 
     option   httplog 
     option   dontlognull 
     retries   3 
     option   redispatch 
     maxconn   500 
     timeout connect 6s 

frontend public 
     mode http 
     bind *:80 
     timeout client 300s 
     option http-server-close 
     #option   http-pretend-keepalive 
     # define ACLs 
     acl host_static hdr_beg(host) -i static. data. 
     acl host_www hdr_beg(host) -i www. 
     acl url_static path_end .ico .txt .pdf .png .jpg .css .js .csv 
     acl is_stats path_beg /haproxy/stats 
     # define rules 
     use_backend nginx if host_static or host_www url_static 
     use_backend stats if is_stats 
     default_backend www 

backend nginx 
     timeout server 20s 
     server nginx 127.0.0.1:8484 

backend stats 
     stats enable 
     stats uri /haproxy/stats 

backend www 
     timeout server 300s 
     option forwardfor 
     #no option httpclose 
     option http-server-close 
     server sockcontent 127.0.0.1:8080 

誰でも知っていますか?それはいくつかのhaproxy設定、またはサーバのいくつかの一般的なネットワーク設定(例えばiptables)に起因するのでしょうか?

P.S. http-pretend-keepalivehaproxyに有効にしようとしましたが、動作しません。

答えて

1

ほとんどの場合、あなたはあなたのネットワークに透過ファイアウォールを持っており、それはそれはケースだ確認するには、ポート80

に行くのWebSocket接続を台無しに:

  1. メイクが別のポートでリッスンしている場合してみてくださいhaproxyそれは働き始めた。
  2. ネットワーク外のサービスにアクセスしてみてください。

動作し始めると、ネットワークに問題があります。

残念なことに、SockJSはこの場合、クライアントが接続していると考えているにもかかわらず、接続が実際に確立されていないため、代替転送を使用しません。

可能な解決策:2つのポート、Webトラフィックのポート80、およびSockJSトラフィックの異なるポートで、ハプロビックがリッスンするようにします。これにより、透過的なHTTPプロキシがwebsocket接続を妨げないことが保証されます。

1

私はすでにこのケースに遭遇しましたが、私はそれがどのサーバーであったのか覚えていませんが、WebSocket仕様に完全に準拠していませんでした。実際には、 "Upgrade"トークンが必要であり、他のものを拒否するよう提案していないのに、 "Upgrade"トークンと共にConnectionヘッダーに "close"トークンが見つかったため失敗しました。

あなたがコメントしたとおりに "option http-pretend-keep-alive"を使用すると理論的にうまくいくはずです。少なくともそれは私のためにした。しかし、ここには別の問題があるかもしれません。

2

@ジョーズと同じように、ファイアウォールが正常に動作していないということです。たとえば、FortiGateが原因となっているとも言われています。

もっと議論:SSL経由https://github.com/sockjs/sockjs-client/issues/94

サービングSockJSは、問題を解決するようです。

関連する問題