我正在使用 docker swarm 运行一个 spring boot 应用程序,并使用 postgres 作为数据库。当我将它们都作为 docker 服务运行时,数据库连接始终随机失败(如您在时间戳上看到的那样),如日志所示:
2017-10-26T17:14:15.200415747Z app-db.1.1ayo6h8ro1og@scw-c2964a | 日志:无法从客户端接收数据:对端重置连接
2017-10-26T17:43:36.481718562Z app-db.1.1ayo6h8ro1og@scw-c2964a | 日志:无法从客户端接收数据:对端重置连接
2017-10-26T17:43:56.954152654Z app-db.1.1ayo6h8ro1og@scw-c2964a | 日志:无法从客户端接收数据:对端重置连接
2017-10-26T17:44:17.434171472Z app-db.1.1ayo6h8ro1og@scw-c2964a | 日志:无法从客户端接收数据:对端重置连接
2017-10-26T17:49:04.154174253Z app-db.1.1ayo6h8ro1og@scw-c2964a | 日志:无法从客户端接收数据:对端重置连接
我无法理解或发现这种情况的原因。如果您能提供任何想法,我将不胜感激。
编辑:
我们意识到,在测试应用程序时,它还会抛出这样的错误:
SQLTransientConnectionException:HikariPool-1 - 连接不可用,请求在 937517 毫秒后超时
谢谢。
答案1
我在部署 Spring Boot 应用程序和 PostgreSQL 的 Docker Swarm 堆栈时遇到了同样的错误。经过大约一周的斗争,我发现问题出在防火墙由于不活动而断开容器之间的连接。快速回答,在 Linux 机器上运行以下 cmd:
sudo sysctl -w \
net.ipv4.tcp_keepalive_time=600 \
net.ipv4.tcp_keepalive_intvl=60 \
net.ipv4.tcp_keepalive_probes=3
另外,我还包含了以下 tomcat 连接池属性:
tomcat:
max-active: 10
initial-size: 5
max-idle: 8
min-idle: 5
test-on-borrow: true
test-while-idle: true
test-on-return: false
test-on-connect: true
validation-query: SELECT 1
validation-interval: 30000
max-wait: 30000
min-evictable-idle-time-millis: 60000
time-between-eviction-runs-millis: 5000
remove-abandoned: true
remove-abandoned-timeout: 60
解决方案来自此博客文章:处理 ELASTICSEARCH 中的 NODENOTAVAILABLE 异常
答案2
还有另一种方法可以防止关闭空闲连接。该问题与默认的 Swarm 服务发现有关,该服务会在 15 分钟后关闭空闲连接。
明确指定dnsrr
端点模式解决问题,例如:
version: '3.3'
services:
foo-service:
image: example/foo-service:latest
hostname: foo-service
networks:
- foo_network
deploy:
endpoint_mode: dnsrr
# ...
networks:
foo_network:
external: true
driver: overlay