使用CockroachDB和HAProxy实现负载均衡器高可用性

参考:查看我之前的文章,我在其中讨论了连接池的高可用性,“使用CockroachDB和PgCat实现连接池高可用性。”


动机

负载均衡器是CockroachDB架构的核心部分。鉴于其重要性,我想探讨克服单点故障(SPOF)场景的方法。

高级步骤

  • 在Docker中启动CockroachDB和HAProxy
  • 运行工作负载
  • 展示容错能力
  • 结论

分步指南

在Docker中启动CockroachDB和HAProxy

I have a Docker Compose environment with all of the necessary services here. Primarily, we are adding a second instance of HAProxy and overriding the ports not to overlap with the existing load balancer in the base Docker Compose file.

I am in the middle of refactoring my repo to remove redundancy and decided to split up my Compose files into a base docker-compose.yml and any additional services into their own YAML files.

  lb2:
    container_name: lb2
    hostname: lb2
    build: haproxy
    ports:
      - "26001:26000"
      - "8082:8080"
      - "8083:8081"
    depends_on:
      - roach-0
      - roach-1
      - roach-2

要跟随操作,您必须使用命令启动Compose环境:

docker compose -f docker-compose.yml -f docker-compose-lb-high-availability.yml up -d --build

您将看到以下服务列表:

 ✔ Network cockroach-docker_default  Created                                                                                 0.0s 
 ✔ Container client2                 Started                                                                                 0.4s 
 ✔ Container roach-1                 Started                                                                                 0.7s 
 ✔ Container roach-0                 Started                                                                                 0.6s 
 ✔ Container roach-2                 Started                                                                                 0.5s 
 ✔ Container client                  Started                                                                                 0.6s 
 ✔ Container init                    Started                                                                                 0.9s 
 ✔ Container lb2                     Started                                                                                 1.1s 
 ✔ Container lb                      Started  

下图描绘了整个集群拓扑:

运行工作负载

此时,我们可以连接到其中一个客户端并初始化工作负载。我使用tpcc,因为它是一个很好的工作负载,可以展示读写流量。

cockroach workload fixtures import tpcc --warehouses=10 'postgresql://root@lb:26000/tpcc?sslmode=disable'

然后我们可以从两个客户端容器启动工作负载。

  • 负载均衡器1:
cockroach workload run tpcc --duration=120m --concurrency=3 --max-rate=1000 --tolerate-errors --warehouses=10 --conns 30 --ramp=1m --workers=100 'postgresql://root@lb:26000/tpcc?sslmode=disable'

  • 负载均衡器2:
cockroach workload run tpcc --duration=120m --concurrency=3 --max-rate=1000 --tolerate-errors --warehouses=10 --conns 30 --ramp=1m --workers=100 'postgresql://root@lb2:26000/tpcc?sslmode=disable'

您将看到类似这样的输出。

  488.0s        0            1.0            2.1     44.0     44.0     44.0     44.0 newOrder
  488.0s        0            0.0            0.2      0.0      0.0      0.0      0.0 orderStatus
  488.0s        0            2.0            2.1     11.0     16.8     16.8     16.8 payment
  488.0s        0            0.0            0.2      0.0      0.0      0.0      0.0 stockLevel
  489.0s        0            0.0            0.2      0.0      0.0      0.0      0.0 delivery
  489.0s        0            2.0            2.1     15.2     17.8     17.8     17.8 newOrder
  489.0s        0            1.0            0.2      5.8      5.8      5.8      5.8 orderStatus

每个HAProxy实例的日志将显示如下内容:

192.168.160.1:60584 [27/Apr/2023:14:51:39.927] stats stats/<STATS> 0/0/0 28724 LR 2/2/0/0/0 0/0
192.168.160.1:60584 [27/Apr/2023:14:51:39.927] stats stats/<STATS> 0/0/816 28846 LR 2/2/0/0/0 0/0
192.168.160.1:60584 [27/Apr/2023:14:51:40.744] stats stats/<STATS> 0/0/553 28900 LR 2/2/0/0/0 0/0
192.168.160.1:60584 [27/Apr/2023:14:51:41.297] stats stats/<STATS> 0/0/1545 28898 LR 2/2/0/0/0 0/0
192.168.160.1:60582 [27/Apr/2023:14:51:39.927] stats stats/<NOSRV> -1/-1/61858 0 CR 2/2/0/0/0 0/0

HAProxy提供了一个Web UI,端口为8081。由于我们有两个HAProxy实例,我将第二个实例的端口设置为8083。

展示容错能力

现在我们可以开始关闭HAProxy实例来演示故障容忍。首先从实例1开始。

docker kill lb
lb

工作负载将开始产生错误消息。

7 17:41:18.758669 357 workload/pgx_helpers.go:79  [-] 60 +                RETURNING d_tax, d_next_o_id]
W230427 17:41:18.758737 357 workload/pgx_helpers.go:123  [-] 61  error preparing statement. name=new-order-1 sql=
W230427 17:41:18.758737 357 workload/pgx_helpers.go:123  [-] 61 +               UPDATE district
W230427 17:41:18.758737 357 workload/pgx_helpers.go:123  [-] 61 +               SET d_next_o_id = d_next_o_id + 1
W230427 17:41:18.758737 357 workload/pgx_helpers.go:123  [-] 61 +               WHERE d_w_id = $1 AND d_id = $2
W230427 17:41:18.758737 357 workload/pgx_helpers.go:123  [-] 61 +               RETURNING d_tax, d_next_o_id unexpected EOF
  142.0s        3            0.0            0.2      0.0      0.0      0.0      0.0 delivery
  142.0s        3            0.0            2.2      0.0      0.0      0.0      0.0 newOrder
  142.0s        3            0.0            0.2      0.0      0.0      0.0      0.0 orderStatus
  142.0s        3            0.0            2.2      0.0      0.0      0.0      0.0 payment

我们的工作负载仍然通过HAProxy 2连接运行。

让我们重新启动它:

docker start lb

注意客户端重新连接并继续执行工作负载。

  335.0s     1780            0.0            0.1      0.0      0.0      0.0      0.0 stockLevel
_elapsed___errors__ops/sec(inst)___ops/sec(cum)__p50(ms)__p95(ms)__p99(ms)_pMax(ms)
  336.0s     1780            0.0            0.1      0.0      0.0      0.0      0.0 delivery
  336.0s     1780            7.0            1.1     19.9     27.3     27.3     27.3 newOrder
  336.0s     1780            0.0            0.1      0.0      0.0      0.0      0.0 orderStatus
  336.0s     1780            2.0            1.0     10.5     11.0     11.0     11.0 payment
  336.0s     1780            0.0            0.1      0.0      0.0      0.0      0.0 stockLevel
  337.0s     1780            0.0            0.1      0.0      0.0      0.0      0.0 delivery
  337.0s     1780            7.0            1.1     21.0     32.5     32.5     32.5 ne

当第二个客户端成功连接时,执行的语句数量增加。

现在我们可以对第二个实例做同样的事情。同样,工作负载报告无法找到lb2主机的错误。

        0.0            0.2      0.0      0.0      0.0      0.0 stockLevel
I230427 17:48:28.239032 403 workload/pgx_helpers.go:79  [-] 188  pgx logger [error]: connect failed logParams=map[err:lookup lb2 on 127.0.0.11:53: no such host]
I230427 17:48:28.267355 357 workload/pgx_helpers.go:79  [-] 189  pgx logger [error]: connect failed logParams=map[err:lookup lb2 on 127.0.0.11:53: no such host]

我们可以观察到语句计数的下降。

我们可以将其重新启动:

docker start lb2

我们可以改进的一点是,启动工作负载时使用两个连接字符串。这将允许每个客户端在其中一个HAProxy实例宕机时切换到另一个实例的pgurl。我们需要做的是停止两个客户端,并使用两个连接字符串重新启动它们。

cockroach workload run tpcc --duration=120m --concurrency=3 --max-rate=1000 --tolerate-errors --warehouses=10 --conns 30 --ramp=1m --workers=100  'postgresql://root@lb:26000/tpcc?sslmode=disable' 'postgresql://root@lb2:26000/tpcc?sslmode=disable'

I am going to do that one client at a time so that the workload does not exit completely.

在这个实验中,我们从未失去对集群进行读写的能力。让我们再次关闭其中一个HAProxy实例,看看影响。

docker kill lb
lb

I’m now seeing errors across both clients, but both clients are still executing.

.817268 1 workload/cli/run.go:548  [-] 85  error in stockLevel: lookup lb on 127.0.0.11:53: no such host
_elapsed___errors__ops/sec(inst)___ops/sec(cum)__p50(ms)__p95(ms)__p99(ms)_pMax(ms)
  156.0s       49            0.0            0.2      0.0      0.0      0.0      0.0 delivery
  156.0s       49            1.0            2.1     31.5     31.5     31.5     31.5 newOrder
  156.0s       49            0.0            0.2      0.0      0.0      0.0      0.0 orderStatus
  156.0s       49            1.0            2.0     12.1     12.1     12.1     12.1 payment
  156.0s       49            0.0            0.2      0.0      0.0      0.0      0.0 stockLevel
I230427 17:55:58.558209 354 workload/pgx_helpers.go:79  [-] 86  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]
I230427 17:55:58.698731 346 workload/pgx_helpers.go:79  [-] 87  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]
I230427 17:55:58.723643 386 workload/pgx_helpers.go:79  [-] 88  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]
I230427 17:55:58.726639 370 workload/pgx_helpers.go:79  [-] 89  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]
I230427 17:55:58.789717 364 workload/pgx_helpers.go:79  [-] 90  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]
I230427 17:55:58.841283 418 workload/pgx_helpers.go:79  [-] 91  pgx logger [error]: connect failed logParams=map[err:lookup lb on 127.0.0.11:53: no such host]

我们可以将其重新启动,并注意到工作负载正在恢复。

结论

在整个实验过程中,我们并未丧失对数据库的读写能力。虽然出现了流量下降的情况,但这是预料之中的。关键在于提供一个高可用的配置,使客户端能够看到多个连接。

Source:
https://dzone.com/articles/load-balancer-high-availability-with-cockroachdb-a