我在使用
Npgsql
时看到奇怪的负载平衡行为。我有一台主服务器和三台备用服务器。由于主服务器可能会发生变化(如果它出现故障并且备用服务器会升级),因此我已将所有四台服务器包含在连接字符串中,但指定应使用备用服务器。
但是,循环实现似乎并不能均匀地平衡负载。在以下示例中,
Primary is host-2
,host-3 获得的连接数量是其他备用服务器的两倍。看起来循环法每次轮到 host-2 时都会检查 host-2 的状态,并发现它是主要的,因此选择了 host-3。然后,循环再次与主机 3 继续循环,这意味着主机 3 在循环期间始终连续获得两个连接。
我在这里做错了什么?
public async Task TestConnections(CancellationToken ct = default)
{
var dataSourceBuilder = new NpgsqlDataSourceBuilder("Host=host-1,host-2,host-3,host-4;Username=***;Password=***;Database=mydb;Load Balance Hosts=True");
await using var dataSource = dataSourceBuilder.BuildMultiHost()
.WithTargetSession(TargetSessionAttributes.Standby);
await using var connection1 = await dataSource.OpenConnectionAsync(ct); // host-1
await using var connection2 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection3 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection4 = await dataSource.OpenConnectionAsync(ct); // host-4
await using var connection5 = await dataSource.OpenConnectionAsync(ct); // host-1
await using var connection6 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection7 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection8 = await dataSource.OpenConnectionAsync(ct); // host-4
await using var connection9 = await dataSource.OpenConnectionAsync(ct); // host-1
await using var connection10 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection11 = await dataSource.OpenConnectionAsync(ct); // host-3
await using var connection12 = await dataSource.OpenConnectionAsync(ct); // host-4
}
这似乎是一个已知问题:https://github.com/npgsql/npgsql/issues/4181
当一个实例关闭时,也会发生类似的情况。这是由 此检查 引起的,它会增加
poolIndex
以使用此列表中的下一个可用池,但不会增加 _roundRobinIndex
,这意味着相同的池将用于下一个连接。
github 问题线程上有关于如何解决此问题的想法,但似乎不确定何时解决此问题。