使用 haproxy,我想要:
- “主”服务器和“备份”服务器的池,但它们不一定必须位于单独的池中。
- 每个后端都有一个较低的“maxconn”(在本例中为 1)
- 客户端不应排队等待。如果“主”池中没有立即可用的服务器,则应立即将其转移到“备用”池。
现在我有一个后端,“主”服务器具有极高的权重并且它“有效”。
acl use_backend
+connslots
是正确的,但没有我自己的答案中的补丁它并不完美。
由于不需要修改 haproxy 二进制文件,因此可获得加分。
答案1
正确的方法是在前端添加一个 ACL,检查服务器上的连接数量,然后根据该数量做出决定。
下面的配置将检查“monitor_conns”前端,如果有 500 个或更多连接,它们将被发送到“备份”后端,否则它们将转到“常规”后端。
这是一个未经测试例子:
frontend monitor_conns
bind *:80
acl too_many_conns fe_conn 500
use_backend backups if too_many_conns
default_backend regular
backend backups
... your config
server backupsrv 192.168.0.101:80 check port 80 maxconn 1000 inter 1s rise 1 fall 1
backend regular
... your config
server regularsrv 192.168.0.100:80 check port 80 maxconn 500 inter 1s rise 1 fall 1
这只是一个例子,但它应该能让你了解如何进行。
答案2
老问题,但我面临同样的问题,这是我的解决方案:
您可以使用 acl 检查前端连接,并使用具有额外服务器的后端,对于该额外服务器,我指的是您的备份服务器
因此配置将如下所示
frontend frontend1 127.0.0.1:9200
mode tcp
acl max_conn_reached fe_conn gt 15
acl production_almost_dead nbsrv(prod1) lt 2
default_backend prod1
use_backend prod1_and_prod2 if max_conn_reached OR production_almost_dead
backend prod1
mode tcp
balance leastconn
server se_prod1 127.0.0.1:8001 check maxconn 10
server se_prod2 127.0.0.1:8002 check maxconn 10
backend prod1_and_prod2
mode tcp
balance leastconn
server se_prod1 127.0.0.1:8001 check maxconn 10
server se_prod2 127.0.0.1:8002 check maxconn 10
server se_backup1 127.0.0.1:8003 check maxconn 10
server se_backup2 127.0.0.1:8004 check maxconn 10
如果前端的连接数大于 15 或者后端 1 上的一个服务发生故障,前端将使用备份服务器(与生产服务器一起)
答案3
以下内容似乎对我有用,但需要修补 haproxy-1.4.15/src/backend.c:
# diff haproxy-1.4.15/src/backend.c backend.c
1298a1299,1333
> /* set test->i to the number of enabled servers on the proxy */
> static int
> acl_fetch_connfree(struct proxy *px, struct session *l4, void *l7, int dir,
> struct acl_expr *expr, struct acl_test *test)
> {
> struct server *iterator;
> test->flags = ACL_TEST_F_VOL_TEST;
> if (expr->arg_len) {
> /* another proxy was designated, we must look for it */
> for (px = proxy; px; px = px->next)
> if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
> break;
> }
> if (!px)
> return 0;
>
> test->i = 0;
> iterator = px->srv;
> while (iterator) {
> if ((iterator->state & SRV_RUNNING) == 0) {
> iterator = iterator->next;
> continue;
> }
> if (iterator->maxconn == 0) {
> test->i = -1;
> return 1;
> }
>
> test->i += (iterator->maxconn - (iterator->cur_sess + iterator->nbpend));
> iterator = iterator->next;
> }
>
> return 1;
> }
>
1461a1497
> { "connfree", acl_parse_int, acl_fetch_connfree, acl_match_int, ACL_USE_NOTHING },
然后我可以connfree
在我的 acl 中使用:
frontend frontend1
bind *:12345
acl main_full connfree(main) eq 0
use_backend backup if main_full
default_backend main
backend main
balance leastconn
default-server maxconn 1 maxqueue 1
server main2 10.0.0.1:12345 check
server main1 10.0.0.2:12345 check
backend backup
balance leastconn
default-server maxconn 1 maxqueue 1
server backup1 10.0.1.1:12345 check
server backup2 10.0.1.2:12345 check
希望通过比较acl_fetch_connfree()
能够acl_fetch_connslots()
明显看出变化:
旧 = (maxconn - 当前连接数) + (maxqueue - 待处理连接数)
new = maxconn-(当前连接数 + 待处理连接数)
答案4
使用后端部分中的“备份”参数
frontend my-frontend *:9091 #arbitrary name for the frontend
maxconn 500
default_backend my-backend
backend my-backend
mode http
option httpchk
server solr-1 10.30.3.100:9091 weight 1 maxconn 500 check
server solr-2 10.30.3.101:9091 weight 1 maxconn 500 check backup
如果 solr-1 无法通过 httpchk,那么 solr-2 将接管。