我在 apache2 服务器上的 preforked(MOD_PHP) 中运行 PHP。设置在 linux Ubuntu 10.04 上。我使用的数据库是firebird 数据库2.5.2。apache2 服务器运行在一个由 8 个网络服务器组成的网络集群中。
在某个时间点,由于对应用程序的请求激增(我们有窥视时间),我们遇到了严重的性能问题。瓶颈显示为解决在很短的时间内出现的请求数量所需的数据库连接数量。Firebird 没有很好地处理它,请求只是超时了。
这种类型的数据库没有连接池,这就是为什么我一直在 PHP 中使用 pconnect 来减轻数据库的压力。这会在 apache2 进程中保持数据库连接。这是一个重大的性能提升。不利的一面是,我们必须让 apache2 进程在轮换之前接受大量请求,并且即使没有负载,我们也要保持大量 apache2 进程运行。每个网络服务器运行 70 个 apache 进程。这是为了保持连接打开并准备就绪。基本上我们试图让 apache2 成为我们的连接池。这行得通。当用户请求应用程序时,数据库句柄已准备就绪,Firebird 不必担心创建新数据库连接的成本。
现在这是我的问题。我们现在需要有很多数据库——小型的。但它们都将在 apache2 服务器集群中运行。这意味着在 apache2 进程的生命周期中,它很可能会获得与多个数据库(可能是 80-100)的持久连接。
我担心 apache2 将如何处理这种情况。apache2 可以处理的连接数是否有限制?它会变慢吗..它会在内存中增长并完美处理所有事情吗?
目前,数据库分片无关紧要。我们(作为开发团队)根本不喜欢拆分数据库的想法。但是重写应用程序并创建新的数据库结构以从代码中获得更多性能并没有绿灯。就目前而言,硬件就是答案。还有一些法律问题迫使我们分成几个数据库来封装数据。但这是我有点担心 apache2 能够处理什么。
有人知道吗?
首先,您应该认真考虑该设计。数据库设计的最佳实践是尽可能避免将数据拆分到多个数据库中。当然,也有例外(例如,如果您需要让客户/应用程序修改其架构),但总的来说,在连接到多个数据库的方向上的可扩展性很差。此外,跨数据库查询很难编写、昂贵且在许多(大多数?)数据库系统中得不到很好的支持,这迫使您做很多本可以由应用程序中的数据库完成的工作。当数据库和应用程序之间存在 N..N 关系时,可维护性是一场噩梦。
其次,您的解释有点不清楚,但我想知道您如何使用您的游泳池..?通常使用 prefork 你会保留一些服务器,以改善延迟。只要服务器存在,持久连接也应该存在。pconnect 并没有真正汇集,听起来也不像你这样做。你能举一个更清楚的例子吗?
第三,有几种资源可以用完。文件描述符很可能会在很早的时候就出现问题,并且来自每个工作人员的许多连接会占用 Apache 和数据库中的内存。此外,即使使用连接池,建立连接也会很昂贵。如果您不能减少正在使用的数据库数量,您很可能不得不承担使用 connect 而不是 pconnect 的成本,以减少陈旧的数据库连接浪费的资源量。
如果有人来找我的设计需要从 Apache 工作人员连接到数百个数据库,我会直接将它们发送回绘图板。这样的设计有太多的事情会出错。合并数据库,或者,如果不可能,则放入中间层。
编辑:好的,现在事情有点清楚了。
这部分是容量规划问题,通常不可能提供好的答案。但是,澄清几点。
如前所述,在尝试建立与多个数据库的连接时,您可能会遇到许多硬限制。文件描述符和内存(尤其是共享内存)可能是您遇到的早期限制。
您所做的并不是真正的连接池,因为持久连接永远不会返回到池中。它只是持久连接,可以为您节省一些开销。
如果我真的必须以这种方式对数据库进行分片(我认为这是一个非常糟糕的设计选择),我的方法是为每个数据库专门分配 Apache 进程。这样我就降低了在一个进程中积累太多持久连接的风险。据我所知,如果不安装多个 Apache2 并根据 FQDN 拆分请求,就无法做到这一点。我会考虑的替代解决方案是消耗使用连接的成本并使用缓存来尽量减少数据库命中的数量,并检查我是否不能将 Web 应用程序与数据库混乱解耦。
是的,它受到其配置参数(MaxClients、MaxServers、KeepAlive、MaxRequestsPerChild 等)和 CPU/内存的限制(使用 KeepAlive,您可以将其中的一些换成另一种)。
是的,连接越多,使用的线程和内存就越多。查看每个 Apache 线程正在使用多少内存(通常为 20 - 30MB),这样您就可以了解在给定可用 RAM 的情况下可以达到的最大值。如果禁用未使用的模块,每个线程将消耗更少的内存。
或者,如果内存是一个问题,您可以考虑使用 Nginx 而不是 Apache,因为 nginx 消耗(少量)固定数量的内存。
在任何情况下,瓶颈通常不会出现在 Web 服务器中,而是出现在数据库和磁盘 I/O 中,这些问题通过缓存和数据库设置/代码/模式优化来解决。
最终,这看起来像是一个容量规划问题,最后确定您的系统是否可以处理多个连接的唯一方法是尝试在测试环境和基准测试中复制设置(或其代表性部分)它。