如果不可用(不仅仅是宕机),请使用备份

如果不可用(不仅仅是宕机),请使用备份

使用 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 将接管。

相关内容