我有两台服务器连接到PostgresSQL 9.6
数据库托管在 Azure 上。服务器正在做一件事 - 使用 a 访问 Postgres 数据库SELECT 1
每5秒查询一次。
连接到数据库并获取数据的典型时间:
- Node:
25 MS
- .NET Core 3.1 使用 Npsql 4.1.1(我也尝试过 4.1.2,没有差异):
500 MS
My problem我的 .NET Core 应用程序是慢 20 倍比Node在获取数据方面。我believe由于某种原因,.NET Core 没有池化连接。在本地运行应用程序和在 Azure 应用服务上运行应用程序时都会出现这种缓慢情况 - 没有区别。我想解决 .NET --> Postgres 缓慢的问题。
请仅浏览相关细节,不要阅读超过此点的全部内容 - 我只相信.NET Core
代码是相关的。
A 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
在数据库上并将该行取出 - 它没有帮助。
我的健康检查控制器如下所示:
// 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
以前,没有区别。
最后,为了防止存在依赖注入问题,存储库位于类库中,API 项目引用它,并且:
services.AddSingleton<IHealthCheckRepository, HealthCheckRepository>();
它是这么看的。
我相信这就是所有相关信息 - 我已经通过电话与 Azure 支持人员联系,他们发现数据库配置没有问题。 .NET Core 应用程序非常轻量,所以它并没有超载,并且正在测试中,所以除了我的测试之外没有流量。
额外:为了完整起见,这是我的整个节点应用程序,它访问数据库并获取发布的性能(取出连接数据)。
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