gpt4 book ai didi

c# - Node 连接到 Postgres 的速度比 .NET Core 快 20 倍

转载 作者:行者123 更新时间:2023-12-03 18:14:03 25 4
gpt4 key购买 nike

我有两台服务器连接到 PostgresSQL 9.6数据库托管在 Azure 上。服务器正在做一件事 - 使用 SELECT 1 访问 Postgres 数据库。每 5 秒查询一次。

连接数据库并获取数据的典型时间:

  • 节点:25 MS
  • .NET Core 3.1 使用 Npsql 4.1.1(我也尝试过 4.1.2,没有差异):500 MS

我的问题是,我的 .NET Core 应用在获取数据方面比 Node 慢 20 倍。我相信 .NET Core 由于某种原因没有池化连接。在本地运行应用程序和在 Azure 应用服务上运行应用程序时都会出现这种缓慢情况 - 没有区别。 我想解决 .NET --> Postgres 缓慢问题。

请仅浏览相关细节,不要阅读超过此点的全部内容 - 我只相信 .NET Core代码是相关的。

一个PsPing从我的机器(Node.NET Core 应用程序都在其上运行:

Connecting to foobarPostGres:5432 (warmup): from someIp: 19.98ms
Connecting to foobarPostGres:5432: from someIp: 1.65ms
Connecting to foobarPostGres:5432 from someIp: 1.18ms
Connecting to foobarPostGres:5432: from someIp: 1.23ms
Connecting to foobarPostGres:5432: from someIp: 1.06ms

为了完整起见,提供 NODE 的示例时间看起来像这样(注意,第一次建立连接时,它也是“慢”):

Attempting to establish a connection...
Elapsed ms: 644.1334999799728
RESP: { '?column?': 1 }
Elapsed ms: 22.76109904050827
RESP: { '?column?': 1 }
Elapsed ms: 21.984400033950806
RESP: { '?column?': 1 }
Elapsed ms: 26.043799996376038
RESP: { '?column?': 1 }
Elapsed ms: 22.538798987865448
RESP: { '?column?': 1 }

.NET Core 的连接时间看起来像这样:

5:13:32 PM: SLOW QUERY, CONN TIME: 4153, QUERY TIME: 18 
5:13:53 PM: SLOW QUERY, CONN TIME: 707, QUERY TIME: 17
5:14:14 PM: SLOW QUERY, CONN TIME: 589, QUERY TIME: 16
5:14:35 PM: SLOW QUERY, CONN TIME: 663, QUERY TIME: 18
5:14:56 PM: SLOW QUERY, CONN TIME: 705, QUERY TIME: 16

请注意,初始连接时间超慢,后续请求建立连接的时间也很长。

无论如何,因为我很绝望,我现在要转储我所有的代码,并附上解释。连接字符串如下所示:

public static string CONNECTION_STRING {
get {
return $"Server={HOST}; User Id={USER}; Database={DB_NAME}; Port={PORT}; Password={PWD}; SSLMode=Prefer";
}
}

据我所知,如果我使用此连接字符串,我应该立即使用连接池。请注意,我尝试过转动 SSL在数据库上并将该行取出 - 它没有帮助。

我的健康检查 Controller 如下所示:

// GET api/health/getdbhealthselectone
[HttpGet]
[Route("getdbhealthselectone")]
public async Task<IActionResult> GetDbHealthSelectOne()
{
int testData = await _healthCheckRepo.RunHealthCheckSelectOne();
return Ok(testData);
}

我的健康检查存储库方法如下所示:

 public async Task<int> RunHealthCheckSelectOne()
{

await using var conn = new NpgsqlConnection(AzureDbConnectionInfo.CONNECTION_STRING);

var connTimer = System.Diagnostics.Stopwatch.StartNew(); // TODO: Remove this testing line
await conn.OpenAsync();
connTimer.Stop(); // TODO: Remove this testing line
var msToConnect = connTimer.ElapsedMilliseconds; // TODO: Remove this testing line

int testData = 999;
var jobsQueryTimer = System.Diagnostics.Stopwatch.StartNew(); // TODO: Remove this testing line0
await using (var cmd = new NpgsqlCommand("SELECT 1", conn))
await using (var reader = await cmd.ExecuteReaderAsync())
while (await reader.ReadAsync()) {
testData = reader.GetInt32(0);
};

jobsQueryTimer.Stop(); // TODO: Remove this testing line
var msToQuery = jobsQueryTimer.ElapsedMilliseconds; // TODO: Remove this testing line

LogQueryIfSlow(msToConnect, msToQuery, _logger); // TODO: Remove this testing line

return testData;
}

注意这里的计时器 - await conn.OpenAsync();到目前为止,这是花费大部分时间的原因,查询本身很快。另外,为了节省时间 - 我运行此代码时没有 async之前没有区别。

最后,为了防止存在依赖注入(inject)问题,存储库位于类库中,API 项目引用它,并且:

services.AddSingleton<IHealthCheckRepository, HealthCheckRepository>();

这就是它的看法。

我相信这就是所有相关信息 - 我已经通过电话与 Azure 支持人员联系,他们发现数据库配置没有问题。 .NET Core 应用程序非常轻量,因此它并没有重载,并且正在测试中,因此除了我的测试之外没有任何流量。

Extra: For the sake of completeness, here is my WHOLE node app which hits the db and gets the performance posted (conn data taken out).

const { Pool, Client } = require('pg');
const { performance } = require('perf_hooks');

const pool = new Pool({
user: 'SECRET',
host: 'SECRET',
database: 'SECRET',
password: 'SECRET',
port: 5432,
})


function runQuery(pool) {
var t0 = performance.now();
pool.query('SELECT 1', (err, res) => {
if (err) {
console.log('ERROR: ', err.stack)
} else {
console.log('RESP: ', res.rows[0])
}
var t1 = performance.now();
console.log('Elapsed ms: ', t1-t0);
//pool.end()
});

}

setInterval(() => {runQuery(pool)}, 5000);
<小时/>

编辑:对于后代,以下是修复连接池超时后 .NET Core 中的时间 - 它比节点更快,除了初始连接,这似乎需要一段时间,但我还没有检查一些默认值:

CONN: 1710 QUERY: 18
CONN: 0 QUERY: 16
CONN: 0 QUERY: 16
CONN: 0 QUERY: 17
CONN: 0 QUERY: 16
CONN: 0 QUERY: 23
CONN: 0 QUERY: 16
CONN: 0 QUERY: 16
CONN: 0 QUERY: 23
CONN: 0 QUERY: 16
CONN: 0 QUERY: 16

最佳答案

您需要设置最小池大小。这样做可以确保无论池使用情况如何,此数量的连接都对数据库保持打开状态。

默认情况下(至少 NPGSQL ),最小大小为 0,因此如果连接一段时间不使用,它将被关闭。

在您的测试中,您每 5 秒执行一次调用,这并不算多,并且池可能会决定关闭未使用的连接。根据文档,它应该保持打开状态 300 秒,而不仅仅是 15 秒

关于c# - Node 连接到 Postgres 的速度比 .NET Core 快 20 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59603244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com