如果不可用则使用备份(不仅仅是停机)

Pri*_*cey 6 haproxy

使用haproxy,我想要:

  • “主”服务器和“备份”服务器池,尽管它们不一定必须位于不同的池中。
  • 每个后端都有一个较低的“maxconn”(在本例中为 1)
  • 客户端不应在队列中等待。如果“主”池中没有立即可用的服务器,则应立即将它们分流到“备份”池。

现在我有一个后端,“主”服务器的权重高得离谱,而且“有效”。

acl use_backend+connslots是正确的,但如果没有我自己的答案中的补丁,它并不完美。

不需要修改 haproxy 二进制文件的奖励积分。

小智 6

正确的方法是在前端添加一个 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
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,但它应该让您了解如何继续。


小智 5

老问题,但我面临同样的问题,这是我的解决方案:

您可以使用 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
Run Code Online (Sandbox Code Playgroud)

如果前端的连接大于 15 或后端 1 上的一项服务关闭,前端将使用备份服务器(与生产服务器一起)


Pri*_*cey 1

以下似乎对我有用,但需要修补 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 },
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

希望比较acl_fetch_connfree()会使acl_fetch_connslots()变化显而易见:

旧 = (maxconn - 当前 conns) + (maxqueue - 待处理 conns)

新 = maxconn - (当前 conns + 待处理 conns)