Таймауты, связанные с базой данных Postgres на Amazon RDS от Azure

Я получаю следующее исключение в своем приложении после оставления соединения с базой данных в течение некоторого времени:

... An I/O error occured while sending to the backend.; nested exception is org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.] with root cause

    java.net.SocketException: Operation timed out
        at java.net.SocketInputStream.socketRead0(Native Method)

То же самое происходит в psql И у меня нет проблем с подключением к локальной базе данных, поэтому я уверен, что проблема связана с RDS.

psql=> select 'ok';
SSL SYSCALL error: Operation timed out
psql=> select 'ok';
SSL SYSCALL error: EOF detected
The connection to the server was lost. Attempting reset: Succeeded.

Я нашел этот другой вопрос, который предлагает работу, которая улучшила ситуацию (таймауты теперь занимают намного больше времени), но не исправили ее.

Я использую Spring Boot с JDBC (пул соединений tomcat) и JDBCTemplate.

Есть ли работа или исправление? Возможно, заставляя пул соединений тестировать и повторно подключаться? Как это сделать в этой среде?

EDIT: Это моя строка соединения

jdbc:postgresql://myhost.c2estvxozjm3.eu-west-1.rds.amazonaws.com/dashboard?tcpKeepAlive=true

РЕШЕНИЕ:

Отредактированы параметры TCP_KeepAlive на стороне сервера RDS, как указано в выбранном ответе. Параметры, которые я использую:

tcp_keepalives_count      5
tcp_keepalives_idle     200
tcp_keepalives_interval 200

Ответ 1

Похоже, что-то - возможно, маршрутизатор NAT на вашем конце, может быть, что-то на AWS-конце - это отслеживание соединений, и через некоторое время забывает о соединениях.

Я предлагаю включить TCP keepalives. Возможно, вы сможете включить их на стороне сервера в конфигурации AWS RDS; если нет, вы можете запросить их на стороне клиента в драйвере JDBC.

TCP keepalives намного лучше, чем запрос проверки/проверки, поскольку они намного ниже накладных расходов, и они не приводят к ненужному спаму журнала в журналах запросов сервера.

Ответ 2

Возможно, попробуйте

spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=true

(см. AbstractDataSourceConfiguration для других опций.)

Ответ 3

В вашей строке подключения вы также включаете порт или только конечную точку? Попробуйте использовать всю конечную точку в строке подключения. Также убедитесь, что группа безопасности, назначенная экземпляру RDS, имеет соответствующие порты и встроенный CIDR.