我正在结合使用 SQLAlchemy 和 Postgres。每隔一段时间我的数据库集群就会替换一个失败的节点,我猜这是生命周期。
我的印象是通过以下方式配置我的引擎:
engine = create_engine(
env_config.pg_connection_string,
echo=False,
pool_size=env_config.pg_pool_size,
pool_timeout=1, # Number of seconds to wait before giving up on getting a connection from the pool.
pool_recycle=3600, # Replace connections on CHECKOUT after 1 hour
connect_args={
'connect_timeout': 10, # Maximum wait for connection
"options": "-c statement_timeout=30s" # Maximum amount of time set for statements
},
)
我的连接会在超过 30 秒的查询时超时,并且我的连接会在尝试 10 秒后超时。
我在实践中注意到的是,在我的数据库节点从我的数据库集群中被替换的情况下,有时需要 15 分钟(900 秒) 来处理像 这样的异常psycopg2.DatabaseError:SSL SYSCALL 错误:没有到主机的路由
。如果在替换节点时数据库事务处于事件状态,它可能需要最多 16 分钟才能引发 SYSCALL 异常。所有新交易都得到很好的处理,我想路由到正确的主机?但是现有的 session /事务似乎会阻塞并停止长达 16 分钟。
我的解释是 SSL SYSCALL 问题既不是连接也不是语句相关设置,因此两个配置的超时都不会产生影响。我的问题仍然是“如何停止或超时这些 SSL SYSCALL 问题?”,我宁愿快速失败并重试相同的查询,也不愿在 阻塞 调用中花费 15 分钟。我不确定在哪里解决这个问题,我猜要么是在我的数据库层(Postgres、SQLAlchemy 或数据库驱动程序)中,要么是在我的网络层 (Centos) 中的配置。
在我的 postgres 配置中进一步挖掘发现,postgres 中 tcp_keepalives_count
和 tcp_keep_alives_interval
的 TCP 相关设置都是 6 和 10。这让我们想知道为什么连接没有60 秒后被杀死。此外,即使没有“到主机的路由”,SSL SYSCALL 问题,是否有可能接收到 TCP ACKS。
最佳答案
除非其他人有更合适的解释,否则我确信我的问题是由 TCP tcp_retries2
和未正常停止打开的数据库连接的组合引起的。每当我的主数据库节点被替换并从集群中删除时,与该节点建立的任何连接都将保持打开状态/处于已建立状态。使用当前的默认 TCP 设置,连接断开前最多可能需要 15 分钟,但不确定为什么会出现 SSL SYSCALL
异常。
涵盖我的问题的这个问题在 PGbounder 存储库中的一个问题/PR 中得到了很好的涵盖:https://github.com/pgbouncer/pgbouncer/issues/138 , TCP 连接在标记为标记/被视为“已死”之前花费了很长时间。
我建议阅读该页面以便更好地理解,我假设我的问题也是由默认 TCP 设置引起的。
长话短说,我认为有两个选择:
- 在我的主机上手动调整 TCP 设置,这将影响该机器上使用组件的所有其他 TCP。
- 设置 PGBouncer 之类的东西,以便可以在本地完成 TCP 调整服务,而不会影响该机器上的任何其他内容。
关于python - SQLAlchemy SSL SYSCALL超时应对机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65505031/