在Kubernetes上使用Npgsql和Pgbouncer - 连接池和保持连接活动状态

3
我正在寻找更详细的指导/其他人在使用Npgsql与Pgbouncer生产环境中的经验。基本上,我们使用GKE和Google Cloud SQL进行以下设置:enter image description here。目前为止,我已经将npgsql配置为如果没有pgbouncer,则使用本地连接池。由于Google SQL具有非常低的最大连接限制,并且为了能够在Kubernetes内部水平扩展应用程序,我已将pgbouncer添加为我的GKE集群中的一个部署 - 我需要保护它免受压倒性的影响。我的问题是当pgbouncer pod之一死亡(由于节点故障或我正在缩放时)时的可靠性问题。当发生这种情况时,(1)所有现有的来自应用程序pod中的客户端连接池的打开连接不会立即关闭(2)-并且基本上会导致我的应用程序出现异常,因为它尝试执行命令。不理想!据我所见(并查看https://www.npgsql.org/doc/compatibility.html中的建议),我有三个选项。1.忍受它,并在我的应用程序中处理SQL命令的重试。可能,但如果我做错了,似乎需要很多努力,并且会创建许多可能的错误。2.打开保持活动状态,并让npgsql自己在这些失败时相对快速地“失败”。我甚至不确定这是否有效或是否会导致进一步的问题。3.完全关闭客户端连接池。这似乎是官方建议,但出于性能原因,我不愿意这样做,这似乎非常浪费Npgsql必须为每个会话打开与pgbouncer的连接-并与其他RDBMS(如SQL Server)的所有经验相反。我选项中的哪一个是正确的?还是我漏掉了什么?
1个回答

5
您大体上是正确的,分析看起来准确。以下是一些评论:
选项2(关闭keepalives)将有助于删除Npgsql池中已经断开的空闲连接。正如您所写的那样,您的应用程序仍然会出现一些故障(因为某些坏的空闲连接可能无法及时删除)。没有特别的理由认为这会引起进一步的问题 - 这应该是相当安全的。
选项3对性能确实有问题,因为每次需要数据库连接时都必须建立到pgbouncer的TCP连接。它也不提供100%的故障保护机制,因为在连接正在使用时,pgbouncer仍可能会退出。

在一天结束时,您所关心的是面对任意网络/服务器故障时的弹性,这并不容易实现。处理这个问题的唯一100%可靠方法是在应用程序中通过专用层重试操作,当出现瞬态异常时。您可能需要查看Polly,请注意Npgsql通过公开IsTransient异常来帮助我们触发重试(Entity Framework Core也包括类似的“重试策略”)。如果您选择这条路,请注意事务特别难以正确处理。


谢谢Shay!来自大人本人的 :) 保持连接似乎是一个好的起点,然后随着时间的推移改进我的应用层(了解IsTransient很有帮助)。根据https://www.npgsql.org/doc/keepalive.html上的建议,还有一个问题 - 是从SQL还是TCP保持连接开始? - Kieran Benton
1
除非我搞错了,否则Npgsql不会意识到由于TCP keepalives失败而导致的连接中断,直到它们被实际使用 - 所以这可能无法解决您的问题。 SQL keepalive通常更安全,因为它不依赖于网络设备的支持。 - Shay Rojansky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接