Повторное подключение к Cloud Postgresql при вызове Cloud Run - PullRequest
0 голосов
/ 17 июня 2020

Я могу подключиться к Cloud Postgresql из Cloud Run, используя unix сокеты, и могу успешно запрашивать базу данных. Однако, если я закрою соединение и попытаюсь открыть новое, весь процесс зависнет, и в конечном итоге время вызова Cloud Run истечет (как и ожидалось, 900 секунд).

Подробности: я использую Dart postgres -dart библиотека для подключения к базе данных. У меня есть оболочка для этой библиотеки, которая реализует пул соединений. Локально все работает нормально: приложение может создать соединение, запросить базу данных, закрыть соединение, выполнить некоторую работу с данными, создать новое соединение, записать результат обратно в базу данных и снова закрыть соединение.

Однако в Cloud Run приложение создает первое соединение, запрашивает базу данных, закрывает соединение, работает с данными и пытается создать новое соединение. Здесь все зависает, и в конечном итоге время вызова Cloud Run истекает.

Нет никаких ошибок и других указаний, которые я могу найти, что что-то пошло не так.

Возможно ли это что Cloud Run обеспечивает соединение только один раз, и оно должно оставаться открытым и повторно использоваться для всего вызова? Учитывая асинхронный c характер Dart, было бы неплохо создавать соединения в зависимости от работы, которую необходимо выполнить, а не блокировать вызовы базы данных. Это также кажется потраченным впустую ресурсом, если соединение остается открытым в зависимости от характера рабочей нагрузки. Я знаю, что могу ограничить количество экземпляров Cloud Run, чтобы ограничить соединения с базой данных, но это не помогает ресурсу t ie -up, если выполняется процесс long-i sh. Но, возможно, мне что-то не хватает в том, как, как ожидается, будет работать Cloud Run.

Кроме этого, я в тупике, потому что он отлично работает вне Cloud Run и есть сообщения об ошибках относительно того, что происходит. Приветствуется любая помощь, подтверждающая, как работает подключение Cloud Run или как проблема может быть диагностирована в Cloud Run.

Edit

Я создал упрощенную конечную точку Cloud Run, которая демонстрирует ту же проблему. Это библиотека, которую я написал, она называется stanza, поверх postgres -dart.

Этот пример чрезвычайно прост - он просто пытается сделать одно и то же дважды, но тот же самый код не запустить во второй раз ...

Future<Response> socketTest(Request req) async {

  final keys = Keys();

  final testTable = TestTable.$table;

  final select = SelectQuery(testTable)
    ..selectFields([testTable.textField, testTable.intField])
    ..orderBy(testTable.id)
    ..limit(1);

  final creds = PostgresCredentials(keys.runDbHost, keys.runDbPort, keys.dbDatabase, keys.dbUser, keys.dbPassword);

  final stanza = Stanza.unix(creds, maxConnections: 5);

  final c1 = await stanza.connection();
  final r1 = await c1.execute<TestTable>(select);
  final out1 = r1.first.value;
  print('${out1.textField} | ${out1.intField}'); // works :)

  final c2 = await stanza.connection();
  final r2 = await c2.execute<TestTable>(select); // hangs :(
  final out2 = r2.first.value; // never reaches here
  print('${out2.textField} | ${out2.intField}');

  return req.response.send.code(200);

}

Cloud Run настроен с экземпляром Postgresql в качестве подключения, учетная запись службы имеет права Cloud SQL Client, и добавлены необходимые переменные среды. Расположение сокета - /cloudsql/PROJECT:REGION:INSTANCE/.s.PGSQL.5432

Мой следующий шаг - попробовать это соединение с меньшим количеством уровней абстракции и посмотреть, смогу ли я заставить его работать . Однако этот код отлично работает при локальном запуске в том же контейнере.

1 Ответ

0 голосов
/ 25 июня 2020

Согласно указанному вами коду, соединение c1 никогда не закрывается, поэтому первое соединение остается, а c2 не может работать. Всегда хорошая практика - тесное соединение, когда вы заканчиваете sh его использовать, я думаю, может быть что-то вроде этого.

final c1 = await stanza.connection();
final r1 = await c1.execute<TestTable>(select);
final out1 = r1.first.value;
print('${out1.textField} | ${out1.intField}'); // works :)
c1 = await stanza.connection().close();

Предлагаю вам взглянуть на этот документ

...