3

ねえ私はsocket.ioからHaproxyプロキシWebSocket接続を取得しようとしています

私はグーグルで見つけることができるほとんどすべてを読み、haproxy.cfgの無数のバリエーションを試しましたが、何を試しても、socket.ioは常に長いポーリングにフォールバックします。

使用しているソケットサーバーに接続を直接ルーティングすると、ws接続が完全に機能することを言及する価値があります。

したがって、socket.ioクライアントとtornadotornadio2websocketサーバーを使用しています。ここから取得した現在のhaproxy.cfghaproxyexample conf

defaults
mode    http

frontend all
bind 0.0.0.0:80
mode tcp

maxconn 200000
timeout client 86400000
default_backend www_backend

# Any URL beginning with socket.io will be flagged as 'is_websocket'
acl is_websocket path_beg /socket.io
acl is_websocket hdr(Upgrade) -i WebSocket
acl is_websocket hdr_beg(Host) -i ws

# The connection to use if 'is_websocket' is flagged
use_backend socket_backend_http if is_websocket

tcp-request inspect-delay 500ms
tcp-request content accept if HTTP   

backend www_backend
option httplog
option httpclose
balance roundrobin
option forwardfor
timeout server 30000
timeout connect 4000
server nginx localhost:81 weight 1 maxconn 1024 check

backend socket_backend_http
mode http
option httplog
option http-server-close
option forceclose
no option httpclose
balance roundrobin
option forwardfor 
timeout queue 5000
timeout server 86400000
timeout connect 86400000
timeout check 1s
server socket1 localhost:3012 weight 1 maxconn 1024 check

websocketリクエストはsocket_backend_httpに正しくルーティングされていますが、ブラウザコンソールには常に次のエラーが表示されます

Unexpected response code: 400

次に、socket.ioは、短時間のメッセージが期待どおりに表示された後、ロングポーリングにフォールバックします。最新バージョンのchrome、safari、firefoxを使用してテストしたところ、すべて同じ結果になりました

私は非常に多くの人々がこれが私を失望させるように働いていると言うのを見てきました!この問題をなんとか解決してくれた人には、永遠に感謝します。

ここでも、haproxyがポット80にバインドされていることを明確にするために、nginxはポート81で実行され、ソケットサーバーはポート3012で実行されています。コード

前もって感謝します

現在のhaproxy.cfgを編集 すると、トルネードサーバーでこのエラーが実際に発生します。

Traceback (most recent call last):
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-     packages/tornado/ioloop.py", line 399, in _run_callback
callback()
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/iostream.py", line 304, in wrapper
callback(*args)
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 250, in _on_headers
self.request_callback(self._request)
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 1362, in __call__
handler._execute(transforms, *args, **kwargs)
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 992, in _execute
self._handle_request_exception(e)
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 1032, in _handle_request_exception
self.send_error(500, exc_info=sys.exc_info())
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 688, in send_error
self.finish()
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 669, in finish
self.request.finish()
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 422, in finish
self.connection.finish()
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 183, in finish
assert self._request, "Request closed"

アップデート

さて、いくつかのさらなる開発。stunnelを使用して、少し異なる設定でこれを機能させることができました。そのため、nginxはhttpリクエストをhttpsに再ルーティングし、そこでピックアップされ、ssl接続はstunnelによって終了されます。その後、ポート8443でリクエストが転送され、haproxyがピックアップされます。ソケットハンドシェイクが行われ、すべてが期待どおりに機能します。これは素晴らしいことですが、httpではなくsslで機能する理由を教えてくれる人が大好きです。

4

4 に答える 4

3

Socket.io について話すことはできませんが、SockJS はテスト済みで、最近の haproxy (たとえば 1.4.16) の背後でうまく動作します。サンプル構成を参照してください。

Nginx の背後で SockJS を実行する方法はまだわかりません。

于 2012-05-18T10:50:54.650 に答える
2

簡単な調査を行いました。個人的にはなじみがありませんが、SockJSを使用していて、同じ動作に気づきました。少なくとも私が見つけたのは、NginxはWebSocketと互換性がなく、HAProxyはあなたが見つけたように動作するように作業を行うということです。 haproxyとsocket.ioが完全に機能していません

サンプル構成は、次のソースhttp://book.mixu.net/ch13.htmlの構成と非常によく似ており、99%類似しています。

https://github.com/mixu/sioconfig/blob/master/single.haproxy.cfg

私が見つけた他の2つのヒントは-HAProxy+WebSocket切断からです

  • HAProxyが1.4以上であることを確認してください
  • socket.ioがバージョン0.6.8以上であることを確認してください
于 2012-05-18T01:28:09.833 に答える
1

明確にするために、WebSocket には HTTP コンテンツがないため、content-length ヘッダーは必要ありません。

また、構成にエラーがあります。フロントエンドは TCP モードであるため、ACL は要求が十分に速く到着した場合にのみ一致します。実際、純粋な運によって部分的に機能する場合もあります。この点を修正するには、フロントエンドを「mode http」に設定し、不要になる「tcp-inspect」ルールを削除してください。ところで、「http-backend」にも HTTP モードがありません。

ログをチェックしていないと思います。そうでなければ、TCP で実際には悪用できないことに気付いたでしょう :-/

于 2012-05-23T22:18:01.733 に答える
0

これは古い質問ですが、

Haproxy は Websocket をプロキシできません (2013 年 6 月現在)。エラーの理由は、通常の http 接続と見なされ、接続がタイムアウトになるためです。タイムアウトを何年も持続させることはできますが、それは汚いと感じます。

オプションは次のとおりです。

  • Nginx バージョン 1.4 では、プロキシ Websocket のサポートが追加されました。http://nginx.org/ を参照してください
  • Nodejitsu の websocket プロキシhttp://blog.nodejitsu.com/http-proxy-introを使用します (同時接続数が 5k を超えるとメモリ リークが発生し、失敗することがわかりました)。
  • 使用などのクライアント側のバランシングserver<n>.x.com
  • amazon の route53 を使用して DNS ラウンドロビンを実行します (ヘルスチェックをサポートしているので amazon と言いましたが、HA が必要ない場合は通常の DNS で十分です)。
  • パニック...

覚えておくべきことの 1 つは、スティッキー セッションを実行するか、集中セッション ストアを使用する必要があることです。SockJS は、各セッションの URL にランダムな文字列を配置するため、socket.io よりも簡単です。これにより、URL に基づいて簡単にバランサーを実行できます。私が不器用だと思った Socket.io とのセッションには、redis などの集中型ストアを使用できます。

Nginx と nodejitsu オプションの両方で、SSL を終了することもできます。

于 2013-06-09T03:21:15.630 に答える