У меня есть два сервера, подключающихся к PostgresSQL 9.6
дБ, размещенной на Azure. Серверы делают одну вещь - нажимают Postgres db с запросом SELECT 1
каждые 5 секунд.
Типичное время для подключения к базе данных и получения данных:
- Узел:
25 MS
- . NET Core 3.1 с использованием N psql 4.1.1 (я тоже пробовал 4.1.2, без различий):
500 MS
My проблема заключается в том, что мое. NET ядро приложения в 20 раз медленнее , чем узел при получении данных. Я верю . NET Ядро по какой-то причине не объединяет соединения. Эта медлительность возникает как при локальном запуске приложения, так и при его запуске в 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
look как это:
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
Обратите внимание на очень медленное начальное время соединения и длительное время для установки sh соединения на последующих запросах.
В любом случае, потому что я в отчаянии, я Я собираюсь сбросить весь мой код с пояснениями. Строка подключения выглядит следующим образом:
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 Базовое приложение очень легкое, поэтому оно не перегружено и не тестируется, поэтому никаких тестов c кроме моих тестов.
Дополнительно: для полноты здесь мое приложение для всего узла, которое попадает в базу данных и публикует результаты (данные сняты).
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 Ядро после исправления тайм-аута пула соединений - оно быстрее, чем узел, за исключением того начального соединения, которое, кажется, занимает некоторое время, но я не проверил некоторые значения по умолчанию:
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