很久以前,在一个遥远的星系中,“线程”是一个很少使用也很少被信任的编程新事物。 在这种环境下,第一批PostgreSQL开发人员决定为每个数据库连接分叉一个进程是最安全的选择。 毕竟,如果你的数据库崩溃了,那将是一种耻辱。
You may also like:
PostgreSQL Connection Pooling With PgBouncer
你可能还喜欢: 带PgBouncer的PostgreSQL连接池
- 从那以后,很多水从桥下流过,但是PostgreSQL社区坚持他们最初的决定。
- 很难指责他们的论点,因为绝对正确的是:
每个客户端都有自己的进程,防止表现不佳的客户端崩溃整个数据库。 在现代Linux系统中,分叉进程和创建线程之间的开销差异比过去小得多。 转向多线程架构将需要大量的重写。 然而,在现代web应用程序中,客户端倾向于打开大量连接。 在进行其他操作时,开发人员通常被强烈劝阻不要保持数据库连接。
尽快打开连接,尽快关闭连接。 但这给PostgreSQL的体系结构带来了一个问题——当事务非常短时,分叉一个过程会变得昂贵,这是常识所要求的。
使用现代语言库确实在一定程度上减少了这个问题——连接池是大多数流行的数据库访问库的一个基本特征。 它确保“关闭的”连接不是真正关闭的,而是返回到一个池中,并且“打开”一个新的连接会返回相同的“物理连接”,从而减少PostgreSQL端的实际分叉。
- 通用连接池的体系结构 然而,现代网络应用很少是单一的,并且经常使用多种语言和技术。
- 在每个模块中使用连接池几乎没有效率:
- 即使模块数量相对较少,每个模块的池大小也较小,但最终还是会有大量的服务器进程。
它们之间的上下文切换代价高昂。 库和语言之间的池支持差异很大——一个表现不佳的池可能会消耗所有资源,并使数据库无法被其他模块访问。 没有集中控制—您不能使用特定于客户端的访问限制等措施。
- 结果,流行的中间件被开发出来用于PostgreSQL。
- 它们位于数据库和客户端之间,有时在单独的服务器(物理或虚拟)上,有时在同一个盒子上,并创建一个客户端可以连接的池。
- 这些中间件是:
针对PostgreSQL及数据库增量同步 其在现代数据库管理系统中相当独特的体系结构进行了优化。 为不同的客户端提供集中的访问控制。 允许你获得与客户端池相同的回报,然后更多(我们将在下一篇文章中更详细地讨论这些)! 连接池几乎是生产就绪的PostgreSQL设置中不可或缺的一部分。
- 虽然使用连接池有很多有据可查的好处,但是 是
- 反对使用一个的一些理由: 在通信中引入中间件不可避免地会引入一些延迟。
但是,当位于同一台主机上时,如果将分叉连接的开销考虑在内,实际上这是可以忽略的,我们将在下一节中看到。 - 中间件成为单点故障。 在这个级别使用集群可以解决这个问题,但是这会增加体系结构的复杂性。
- 避免单点故障的中间件冗余:来源 中间件意味着额外的成本。
- 您需要一个额外的服务器(或3个),或者您的数据库服务器必须有足够的资源来支持除PostgreSQL之外的连接池。 不同模块之间的共享连接可能会成为安全漏洞。
非常重要的一点是,我们要配置pgPool或PgBouncer,以便在连接返回到池中之前清除它们。 - 身份验证从数据库管理系统转移到连接池。
- 这并不总是可以接受的。
保镖认证模型:来源 它增加了攻击的表面积,除非对底层数据库的访问被锁定,只允许通过连接池进行访问。 它还创建了另一个必须维护的组件,根据您的工作负载进行微调,经常进行安全修补,并根据需要进行升级。
然而,所有这些问题在PostgreSQL社区中都有很好的讨论,缓解策略确保连接池的优点远远超过它们的缺点。
我们的测试表明,即使是少数客户端也可以从使用连接池中受益匪浅。
它们非常值得额外的配置和维护工作。