我有一个运行 HAProxy(balance = source)的 Amazon OpsWorks 堆栈和几个运行 socket.io 的 node.js 实例。看来 HAProxy 根据给定实例的内存限制来确定该实例的最大会话限制,这很好,但我的应用程序通常可以预期客户端使用两个页面(均连接到套接字)长达 4 小时。
如果最大会话限制为 40 或 180,那么我只能同时拥有 20/60 个客户端,直到其中一个断开连接。因此,如果达到限制,其他客户端将被放入队列中,直到有空闲位置,而考虑到站点的性质,这种情况可能在一段时间内不会出现。这意味着我的站点只能为少数人提供服务。
解决这个问题的最佳方法是什么?我读了几篇文章,其中他们的后端有 4,000 - 30,000 个,每个服务器的最大会话限制只有 30 个,但他们如何实现这一点?HAProxy 中是否有设置,或者更有可能通过实际应用程序不断重新连接/断开客户端?
编辑
为了进一步说明该应用程序 - 它本身是一个 PHP 应用程序,利用套接字处理实时事件。这些套接字是通过socket.io
使用生成的服务器完成的express
。此server.js
文件与 Amazon ElastiCache Redis 服务器通信(据我了解,socket.io 1.0 处理所有后端)。
在客户端,用户连接到套接字服务器并发出连接事件,以便加入他们独有的房间。然后,用户将加载第二个页面并再次发出连接事件并加入同一个唯一的房间。这样他们就可以在会话过程中发出和接收各种事件 - 同样,此会话可以持续 4 个小时以上。
HAProxy 根据用户的 IP 哈希将用户路由到同一个服务器(balance source
) - 其余选项保持为 OpsWorks 默认值 - 请参阅下面的配置文件。
我想我需要知道的是,如果Cur
会话达到 40 个,并且这些连接是长期存在的(即它们不会轻易断开),队列中的那些人会发生什么?如果他们等了 4 个小时,显然就不好了。
--
HAProxy的配置文件
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
#log loghost local0 info
maxconn 80000
#debug
#quiet
user haproxy
group haproxy
stats socket /tmp/haproxy.sock
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 80000
timeout client 60s # Client and server timeout must match the longest
timeout server 60s # time we may wait for a response from the server.
timeout queue 120s # Don't queue requests too long if saturated.
timeout connect 10s # There's no reason to change this one.
timeout http-request 30s # A complete request may never take that long.
option httpclose # disable keepalive (HAProxy does not yet support the HTTP keep-alive mode)
option abortonclose # enable early dropping of aborted requests from pending queue
option httpchk # enable HTTP protocol to check on servers health
stats auth strexm:OYk8834nkPOOaKstq48b
stats uri /haproxy?stats
# Set up application listeners here.
listen application 0.0.0.0:80
# configure a fake backend as long as there are no real ones
# this way HAProxy will not fail on a config check
balance source
server localhost 127.0.0.1:8080 weight 1 maxconn 5 check
服务器.js
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: ###, port: 6379 }));
server.listen(80); // opsworks node.js server requires port 80
app.get('/', function (req, res) {
res.sendfile('./index.html');
});
io.sockets.on('connection', function (socket) {
socket.on('join', function(room) {
socket.join(room);
});
socket.on('alert', function (room) {
socket.in(room).emit('alert_dashboard');
});
socket.on('event', function(data) {
socket.in(data.room).emit('event_dashboard', data);
});
});
客户
var socket = io.connect('http://haproxy_server_ip:80');
socket.on('connect', function() {
socket.emit('join', room id #);
});
答案1
我不认为 haproxy 设置了这些限制。我怀疑可能对允许来自同一 IP 地址的会话数有限制,因此如果您从一台机器进行测试,那么这可能是您的问题。Haproxy 确实可以轻松处理 1/1000 个连接。
答案2
在未看到您谈论的任何配置和您谈论的网站的情况下,我不得不猜测他们正在使用 实现标准 Web 应用程序上的会话数http-server-close
。因此,在这种情况下,您拥有大量短暂的连接。
一个更好的例子是 Web 套接字,这是一种非常长的连接。对于 SE 网络,我们将maxconns
Web 套接字层设置为 500,000。
您真正想要做的是确定您希望在任意给定时间能够支持的并发连接数,并将maxconn
值设置为该值。当然,您必须确保负载均衡器上有足够的资源来支持您选择的数量。