3

嘿,我一直在尝试从 socket.io 获取 Haproxy 代理 websocket 连接

我已经阅读了我在谷歌上能找到的几乎所有内容,并尝试了 haproxy.cfg 的无数变体,但无论我尝试什么,socket.io 总是退回到长轮询。

值得一提的是,如果我将连接直接路由到我正在使用的套接字服务器,则 ws 连接可以完美地工作。

所以我使用 socket.io 客户端和 tornado tornado2 websocket 服务器。我当前的 haproxy.cfg 取自这里haproxy example 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 并被 stunnel 终止,然后将请求转发到 haproxy 接收的端口 8443 上。套接字握手已完成,一切都按预期工作,这很好,但我喜欢有人能够启发我为什么这适用于 ssl 而不是 http !!!

4

4 回答 4

3

我不能谈论 Socket.io,但 SockJS 已经过测试,并且在最近的 haproxy(例如 1.4.16)之后运行良好。查看示例配置:

我还没有想出在 Nginx 后面运行 SockJS 的方法。

于 2012-05-18T10:50:54.650 回答
2

做了一些快速的研究——个人并不熟悉,但我一直在使用 SockJS 并注意到同样的行为。我至少发现 Nginx 与 websockets 不兼容,并且 HAProxy 需要努力才能开始工作,就像你发现的那样。 haproxy 和 socket.io 无法正常工作

示例配置与来自以下来源http://book.mixu.net/ch13.html的配置非常相似,看起来与您的配置有 99% 的相似性。

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

我发现的另外两个花絮是 - 来自HAProxy + WebSocket Disconnection

  • 确保您的 HAProxy 为 1.4 或更高版本
  • 确保您的 socket.io 是 0.6.8 或更高版本
于 2012-05-18T01:28:09.833 回答
1

为了清楚起见,WebSocket 中没有 HTTP 内容,因此不需要任何 content-length 标头。

此外,您的配置中存在错误。前端处于 TCP 模式,因此 ACL 仅在请求来得足够快时才会匹配。事实上,有时它可能部分靠运气。请将您的前端设置为“模式 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 roundrobin(我说amazon是因为它支持健康检查,但是如果你不需要HA,普通的DNS就可以了)
  • 恐慌...

要记住的一点是,您还需要进行粘性会话或使用集中式会话存储。SockJS 比 socket.io 更容易做到这一点,因为它会在每个会话的 url 中放置一个随机字符串,因此您可以简单地基于 url 进行平衡器。您可以使用集中式存储(例如 redis)与 Socket.io 进行会话,我觉得这很笨拙。

Nginx 和 nodejitsu 选项都可以为您终止 SSL。

于 2013-06-09T03:21:15.630 回答