Postgresql Ошибка ввода-вывода при отправке на сервер с помощью приложения Java - PullRequest
3 голосов
/ 09 апреля 2020

Я использую сервис Amazon RDS для размещения Postre Sql, который служит базой данных для моего Java приложения. После запуска приложения оно может выполнять запросы, как и ожидалось, пока я не перестану взаимодействовать на несколько минут и попытаюсь выполнить любой запрос снова. В этом сценарии я получаю следующее исключение:

WARNING: Validating connection.
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:327)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
    at org.postgresql.jdbc.PgConnection.isValid(PgConnection.java:1311)
    at org.apache.commons.dbcp2.DelegatingConnection.isValid(DelegatingConnection.java:897)
    at org.apache.commons.dbcp2.PoolableConnection.validate(PoolableConnection.java:270)
    at org.apache.commons.dbcp2.PoolableConnectionFactory.validateConnection(PoolableConnectionFactory.java:630)
    at org.apache.commons.dbcp2.PoolableConnectionFactory.validateObject(PoolableConnectionFactory.java:648)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:472)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:349)
    at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)
    at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:753)

Caused by: java.net.SocketException: Operation timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:140)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:109)
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:67)
    at org.postgresql.core.PGStream.receiveChar(PGStream.java:288)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1962)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)

В Amazon RDS PostgreSQL я вижу следующие ошибки:

2020-04-09 19:01:11 UTC::[]:LOG: could not receive data from client: Connection timed out
2020-04-09 19:04:27 UTC::@:[]:LOG: checkpoint starting: time
2020-04-09 19:04:28 UTC::@:[]:LOG: checkpoint complete: wrote 1 buffers (0.0%); 0 WAL file(s) added, 0 removed, 1 recycled; write=0.143 s, sync=0.001 s, total=0.154 s; sync files=1, longest=0.001 s, average=0.001 s; distance=16377 kB, estimate=16396 kB
2020-04-09 19:08:15 UTC::LOG: could not receive data from client: Connection timed out

Есть идеи, как решить эту проблему?

Ответы [ 3 ]

1 голос
/ 16 апреля 2020

Полагаю, у вас есть (виртуальный) сетевой компонент, такой как маршрутизатор, балансировщик нагрузки, межсетевой экран с отслеживанием состояния и т. Д. c. он решает, что через X секунд ваше соединение может быть удалено, сохранив часть драгоценной памяти. Это, однако, не информируя обе стороны о TCP-соединении (базе данных или вашем приложении Java), поэтому через некоторое время они заметят, что они больше не связаны друг с другом.

Если вы не можете изменить поведение Компоненты вашей сети, которые молча уничтожают ваши соединения, вы можете выбрать из следующих опций:

  1. Настройте ваш пул соединений (DBCP или, если вам не нравится, переключитесь на HikariCP), чтобы активно закрывать незанятые соединения, перед тем как указанное выше время ожидания см. в инструкциях этот древний поток
  2. Сконфигурируйте пул соединений, чтобы он продолжал проверять работоспособность бездействующих соединений, что будет поддерживать соединение в действии
  3. Использование Функции TCP из операционной системы (TCP KeepAlive):

    • Включение этой функции в сокете через драйвер JDB C с помощью: tcpKeepAlive = "true"
    • Настройка работы Системные настройки времени активности для передачи пакетов активности до истечения времени ожидания, см .: Linux документы или эти Windows настройки реестра
  4. Не используйте пул соединений (но это плохо сказывается на производительности, см. : этот ответ для более подробной информации )

0 голосов
/ 16 апреля 2020

Я сталкивался с этой проблемой однажды, и это сводило меня с ума. В конечном итоге проблема заключалась в том, что брандмауэр останавливал любое простаивающее соединение более чем на 30 минут без уведомления бэкэнда

0 голосов
/ 15 апреля 2020

Я вижу здесь потенциальную проблему, возможно, у вас не хватает соединений в вашем пуле соединений с вашей postgres БД, возможно, это связано с тем, что существующее соединение может не закрыться после транзакции с БД и не используется повторно новая входящая транзакция. Попробуйте использовать pgbouncer, чтобы решить эту проблему. Это мое предположение, видя ваши журналы

...