我可以通过身份验证与 HAProxy 和 socket.io 建立粘性会话吗?

发布于 2024-12-15 20:49:54 字数 1519 浏览 6 评论 0原文

我有几个在 HAProxy 下运行身份验证的 socket.io 实例,我需要强制身份验证请求和套接字连接转到同一个实例。我已经根据这个问题的答案设置了HAProxy,并进行了一些修改:所以:

global
    maxconn     4096 # Total Max Connections. This is dependent on ulimit
    nbproc      2

defaults
    mode        http

frontend all 0.0.0.0:80
    timeout client 86400000
    default_backend www_backend
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws

    use_backend socket_backend if is_websocket

backend www_backend
    balance url_param sessionId
    option forwardfor # This sets X-Forwarded-For
    timeout server 30000
    timeout connect 4000
    server server1 localhost:8081 weight 1 maxconn 1024 check
    server server2 localhost:8082 weight 1 maxconn 1024 check
    server server3 localhost:8083 weight 1 maxconn 1024 check

backend socket_backend
    balance url_param sessionId
    option forwardfor # This sets X-Forwarded-For
    timeout queue 5000
    timeout server 86400000
    timeout connect 86400000
    server server1 localhost:8081 weight 1 maxconn 1024 check
    server server2 localhost:8082 weight 1 maxconn 1024 check
    server server3 localhost:8083 weight 1 maxconn 1024 check

我已经尝试过 url_param (其中 sessionId 是在身份验证调用和 websocket 连接中传递的查询字符串参数)和 source 作为平衡选项,但似乎如果 HAProxy 仅允许 HTTP 连接使用这些选项,因此在实际的 Websocket 连接中忽略它们。结果是有时身份验证请求和套接字连接最终位于不同的服务器中,这对于我们的应用程序来说是不可接受的。

有什么方法可以实现这种理想的行为吗?

I have several instances of socket.io with authentication running under HAProxy and I need to force that the authentication request and the socket connection go to the same instance. I've set up HAProxy based on this answer to a SO question with some modifications as so:

global
    maxconn     4096 # Total Max Connections. This is dependent on ulimit
    nbproc      2

defaults
    mode        http

frontend all 0.0.0.0:80
    timeout client 86400000
    default_backend www_backend
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws

    use_backend socket_backend if is_websocket

backend www_backend
    balance url_param sessionId
    option forwardfor # This sets X-Forwarded-For
    timeout server 30000
    timeout connect 4000
    server server1 localhost:8081 weight 1 maxconn 1024 check
    server server2 localhost:8082 weight 1 maxconn 1024 check
    server server3 localhost:8083 weight 1 maxconn 1024 check

backend socket_backend
    balance url_param sessionId
    option forwardfor # This sets X-Forwarded-For
    timeout queue 5000
    timeout server 86400000
    timeout connect 86400000
    server server1 localhost:8081 weight 1 maxconn 1024 check
    server server2 localhost:8082 weight 1 maxconn 1024 check
    server server3 localhost:8083 weight 1 maxconn 1024 check

I've tried url_param (where sessionId is a querystring parameter passed in both the authentication call and the websocket connection) and source as the balance options but it seems as if HAProxy only allows these options for HTTP connections and so ignores them for the actual websocket connection. The result is that sometimes the auth request and the socket connection end up in different servers, which is unacceptable for our application.

Is there some way to have this desired behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

压抑⊿情绪 2024-12-22 20:49:54

我以这种方式使用基于 cookie 的平衡:

backend socketio
    mode http
    cookie SIO insert
    server sock1 127.0.0.1:8001 cookie 001
    server sock2 127.0.0.1:8002 cookie 002

I use cookie based balancing in this way:

backend socketio
    mode http
    cookie SIO insert
    server sock1 127.0.0.1:8001 cookie 001
    server sock2 127.0.0.1:8002 cookie 002
萌逼全场 2024-12-22 20:49:54

为了平衡 TCP 连接,您可以使用 stick_matchstick on 命令并显式设置 tcp 模式,通过粘性表取得一些成功。

以下是一个示例:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

此处提供完整文档。

To balance TCP connection, you may have some success with a stickiness table using the stick_match or stick on commands and explicitly setting tcp mode.

Here is an example:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

Full documentation available here.

浪推晚风 2024-12-22 20:49:54

对于 websocket 连接,使用roundrobin 进行平衡。由于它是双向套接字(通过 TCP),默认情况下会保持粘性。对于其他传输,使用source平衡算法是最好的选择。 (您可以使用基于 cookie 的持久性,但 socket.io 不会将 JSESSIONID 等发送回代理服务器。您可以尝试 sockjs(如果您想要基于 cookie 的持久性)。)

示例:

#do the same for other transports. [Note in 0.6.x resource was mounted at path: /socket.io/[transport]
acl is_JSONPolling path_beg /socket.io/1/jsonp-polling
use_backend non_websocket if is_JSONPolling


backend non_websocket
  balance source
  #rest same as the one for websocket backend

For websocket connections balance using roundrobin. Since its a Bidirectional socket (over TCP) stickyness is maintained by default. For other transports using source balancing algorithm is the best bet. (You can use cookie based persistence but socket.io doesn't send a JSESSIONID or the like back to the proxy server. You can try sockjs if you want cookie based persistence.)

Example:

#do the same for other transports. [Note in 0.6.x resource was mounted at path: /socket.io/[transport]
acl is_JSONPolling path_beg /socket.io/1/jsonp-polling
use_backend non_websocket if is_JSONPolling


backend non_websocket
  balance source
  #rest same as the one for websocket backend
囍孤女 2024-12-22 20:49:54

您使用的是 HTTP,因此请插入一个 cookie 以实现持久性 - 这绝对是最佳途径。这会将其粘贴到他们访问的第一台服务器上,除非该服务器出现故障。

您还可以配置是否在宕机等情况下重新调度它。

You're using HTTP so insert a cookie for persistence - that's definitely the best route. That'll stick it to the first server they went to unless it's down.

You can also configure whether it should redispatch it if it is down etc.

离笑几人歌 2024-12-22 20:49:54

就我而言,我需要使用 Authorization: Bearer ${ACCESS_TOKEN} 对用户进行身份验证,对于这种身份验证,您可以使用 stick_tables

以下配置将平衡器主机端口 80 设置为跟踪并坚持 Authorization 标头相同的连接:

frontend :80
   mode http
   bind :80
   default_backend http_servers

backend http_servers
    balance roundrobin
    stick-table type string len 600 size 1000m expire 5m
    stick on req.hdr(Authorization)
    server server81 192.168.1.1:81 weight 1 maxconn 512 check
    server server82 192.168.1.1:82 weight 1 maxconn 512 check
    server server83 192.168.1.2:83 weight 1 maxconn 512 check

In my case I needed to authenticate the user using an Authorization: Bearer ${ACCESS_TOKEN}, for that kind of authentication you can use stick_tables.

The following configuration sets the balancer-host port 80 to track and stick whose connections where the Authorization header is the same:

frontend :80
   mode http
   bind :80
   default_backend http_servers

backend http_servers
    balance roundrobin
    stick-table type string len 600 size 1000m expire 5m
    stick on req.hdr(Authorization)
    server server81 192.168.1.1:81 weight 1 maxconn 512 check
    server server82 192.168.1.1:82 weight 1 maxconn 512 check
    server server83 192.168.1.2:83 weight 1 maxconn 512 check
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文