L'exception suivante s'affiche dans mon application après avoir laissé une connexion de base de données inactive pendant un certain temps:
... 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)
Le même problème se produit dans psql ET je n'ai pas de problèmes de connexion à une base de données locale, je suis donc presque certain que le problème concerne 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.
J'ai trouvé cette autre question qui suggère un travail de contournement qui a amélioré la situation (les délais d'attente prennent maintenant beaucoup plus de temps) mais n'a pas résolu le problème.
J'utilise Spring Boot avec JDBC (regroupement de connexions Tomcat) et JDBCTemplate.
Y at-il un travail autour ou une solution? Peut-être obliger le pool de connexions à tester et à se reconnecter? Comment puis-je faire cela dans cet environnement?
EDIT: Ceci est ma chaîne de connexion
jdbc:postgresql://myhost.c2estvxozjm3.eu-west-1.rds.amazonaws.com/dashboard?tcpKeepAlive=true
SOLUTION:
Modifiez les paramètres TCP_KeepAlive du serveur côté RDS comme suggéré dans la réponse sélectionnée. Les paramètres que j'utilise sont:
tcp_keepalives_count 5
tcp_keepalives_idle 200
tcp_keepalives_interval 200
Cela ressemble à quelque chose - peut-être un routeur NAT de votre côté, peut-être quelque chose du côté de AWS - est le suivi de connexion et oublie les connexions au bout d'un moment.
Je suggère permettant TCP keepalives . Vous pourrez peut-être les activer côté serveur dans la configuration AWS RDS; sinon, vous pouvez les demander côté client dans le pilote JDBC.
Les keepalives TCP sont bien meilleurs qu'une requête de validation/test, car ils nécessitent beaucoup moins de temps système et ne génèrent pas de spam inutile dans les journaux de requête du serveur.
Dans votre chaîne de connexion, incluez-vous également le port ou uniquement le point final? Essayez d’utiliser l’ensemble du noeud final dans votre chaîne de connexion. Vérifiez également que le groupe de sécurité affecté à l'instance RDS dispose des ports et du CIDR entrant définis.
Peut-être essayer
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=true
(Voir AbstractDataSourceConfiguration
pour d'autres options.)