Таймауты, связанные с базой данных 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.