5

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

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

を使用してサーバーにデプロイすると、接続が開いていると思われるHAProxy奇妙なことが起こります (コンソール ログに「msg sent」が表示されます) 。以下は、ログに表示されるものです。sockjsconn.readyState === SockJS.OPENwebsockethaproxy

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"

2 番目のログ メッセージは、バックエンド サーバーをシャットダウンしたときにのみ表示されることにhaproxy注意してください。シャットダウンする前に、ログにエラーはありませんが、websocket ハンドシェイクは完了せず、サーバーはメッセージを受信しません。

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)が原因ですか?

http-pretend-keepalivePS で有効にしようとしましhaproxyたが、機能しません。

4

3 に答える 3

2

@Joesが言ったように、それはファイアウォールの誤動作のせいです。たとえば、FortiGate が原因であると言う人もいます。

詳細な議論: https://github.com/sockjs/sockjs-client/issues/94

SSL経由でSockJSを提供すると、問題が解決するようです。

于 2012-10-30T11:07:53.957 に答える
1

ほとんどの場合、ネットワークにトランスペアレント ファイアウォールがあり、ポート 80 への WebSocket 接続が混乱します。

そうであることを確認するには、次のようにします。

  1. haproxy を別のポートでリッスンし、動作を開始したかどうかを試してください。
  2. ネットワーク外でサービスにアクセスしてみてください。

機能し始めた場合は、ネットワークに問題があります。

残念ながら、この場合、SockJS はフォールバック トランスポートを使用しません。これは、クライアントが接続したと認識しているが、実際には接続が確立されていないためです。

可能な解決策として、haproxy が Web トラフィック用のポート 80 と SockJS トラフィック用の別のポートの 2 つのポートでリッスンするようにします。これにより、透過的な HTTP プロキシが WebSocket 接続を台無しにしないことが保証されます。

于 2012-10-24T20:36:25.770 に答える
1

私はすでにこのケースに遭遇しました。それがどのサーバーだったかは覚えていませんが、WebSocket 仕様に完全に準拠していませんでした。確かに、接続ヘッダーに「アップグレード」トークンとともに「クローズ」トークンが見つかったため失敗しましたが、仕様では「アップグレード」トークンが必要であり、(幸いなことに) 他のトークンを拒否することは示唆されていません。

理論的には、コメントしたように「オプション http-pretend-keep-alive」を使用すると、機能するはずです。少なくとも私にはそうでした。しかし、ここには別の問題があるのか​​もしれません。

于 2012-10-23T15:36:29.107 に答える