10

在以下方面设置游泳池的最佳方法是什么: -

  1. 你什么时候创建连接?
  2. 你什么时候关闭连接,你会关闭所有连接吗?
  3. 你测试连接还是不错的。何时以及如何?
  4. 您如何确定最大连接数的好数字?
  5. 你有什么样的监控来确保池的用户表现良好?你能阻止一段糟糕的代码带走所有东西吗?
  6. 您是否编写了自己的池,或使用了第三方库?

我相信这是一个不可知论的问题,但欢迎对特定数据库/语言的“功能”发表评论。例如,在某些数据库上连接可能比其他数据库更慢或更昂贵。

澄清一下,我不打算从头开始编写一个池,这个问题更多的是关于如何配置一个现有的池化库。

4

6 回答 6

6

当它只是一种设计模式而不是通用库时,我用 Java 为数据库编写了一个连接池。现在我使用 Tomcat 中内置的那个。

我用一个线程来监控池的几个方面和几个参数来控制它的行为......

  1. minimumInPool="3"... 前三个是在启动时创建的。游泳池永远不允许低于三。
  2. maximumIdleTimeBeforeRemoval="60"... 如果一个连接空闲一个小时,则删除它并创建一个新连接。空闲时间可能意味着池中只有最少三个。
  3. maximumInUseTimeBeforeRemoval="30"... 如果给定的连接已签出超过 30 分钟,则可能有问题。召回它,并终止连接。
  4. maximumTimeBeforeRemoval="60"... 如果超过 60 分钟,请将其删除。
  5. maximumUsageBeforeRemoval="1000"... 如果已签出超过 1000 次,请将其删除。
  6. monitorInterval="15"... 每 15 分钟检查一次上述参数。

几年来,这对我很有帮助。在一次狂野的窥视中,我见过的池中最高的是 151 个连接。通常游泳池在大量使用期间大约有十几个,并且在清晨空闲到最少三个。

我使用 Oracle 的 JDBC 瘦驱动程序并连接到 Oracle 数据库。

于 2008-11-07T05:09:34.777 回答
3

这是我用于最近实施的基本原理。

  1. 在您的连接池中有两种连接。第一个是准备好的,意思是打开但没有被客户使用。第二个是活动的,意思是客户正在使用。

  2. 让您的连接池维护少量就绪连接,最小 N 和最大 M。N 可以根据客户端请求连接的峰值速度进行调整。如果就绪连接的数量下降到零,则需要更大的 N。如果数量一直很高(比如 10 以上),则需要更低的 N。

  3. 当客户端想要一个连接时,给他们一个准备好的连接(使其处于活动状态),然后如果现在准备好的少于 N 个,则立即打开一个新连接(但不要让客户端等待完成,否则你将失去池化的优势)。这确保始终有至少 N 个就绪连接。如果当客户想要一个时没有准备好,他们将不得不等待你创建一个新的。

  4. 当客户端完成一个活动连接时,如果就绪连接少于 M 个,则将其返回到就绪状态。否则关闭它。这可以防止您拥有超过 M 个准备好的连接。

  5. 定期回收准备好的连接以防止陈旧的连接。如果有超过 N 个就绪连接,只需关闭最旧的连接。否则关闭它并重新打开另一个。

这样做的好处是在您的连接池中有足够的就绪和年轻的连接可用,而不会使服务器过载。

于 2008-11-07T04:34:15.473 回答
2

我不确定您使用连接的背景是什么,但我可以分享似乎对我有用的东西。

我使用 SQL Server 作为后端,并结合使用缓存来获得更好的性能。我的做法是仅在我真正需要它时才保持连接打开,而不是连接池,以便它们立即清理,我可以在 SQL Activity 监视器中确切地看到什么是活动的,什么不是。每个连接都会占用内存,因此在不需要它们时将其保持在沉闷的轰鸣声是很好的。

在我回答连接打开和关闭问题之前,让我说缓存非常重要。从缓存中取出一个对象将为您节省大量时间。在我的一些 asp.net 应用程序中,当缓存在 dev 中打开时,我发现我几乎无法测量延迟,而使用数据库调用可能需要 15 毫秒到 45 毫秒才能完成调用,这甚至没有考虑其他延迟因素或负荷。我使用的另一种方法是为我的数据提供良好的对象结构,这样我只在发生变化时才进行数据库更新。我已经在我的对象上实现了一些方法,确保我做的 IO 尽可能少。

话虽如此,我们都知道我们需要在某个时候访问和写入我们的数据库,所以我遵循两个原则:

  1. 保持门窗关闭以节省能源。一个地方的开放连接意味着它在另一个地方不可用(或者内存和其他资源更加有限)。我们关闭了池化,因为它为我们带来了更好的性能。

  2. 当连接打开时,我会尽可能多地批量或一次。这有点复杂,所以让我解释一下。

    • 我使用的一种方法是将连接对象传递到管道中,以便所有对象都可以使用一个连接对象。这会导致打开和关闭一个连接,而不是 10 个或更多,具体取决于您的应用程序。一个很好的例子是我们的一种采购模型,它利用 SQL 服务器的强大功能来收集统计数据和散列复杂的订购模式。当您进行 200K+ 数据库查找或任何应用程序的用途时,继续打开和关闭连接是没有意义的。另一部分是,当我使用对象时,我会尝试捆绑更新以减少保持连接打开的时间。因此,在 insert 调用上执行 scope_identity 让我在缓存之前处理我的插入和查找要添加到我的对象的唯一 ID。回到我第一次开发 asp 应用程序的那一天,我实际上会在页面开始加载时打开连接,然后再关闭它。我不建议再这样做了。现在有一天,这些抽象和层有很大的好处,我建议任何新手程序员都仔细注意。

我的两分钱:

缓存您的数据!缓存您的数据!缓存您的数据!当您无法缓存然后缓存您的数据时,请尽可能少地访问数据库!

于 2008-11-07T05:30:58.523 回答
2

Jakarta Commons DBCP 已经完成了您列出的所有内容:

  • 它根据需要创建连接并在池中管理它们
  • 如果一段时间未使用,它可以关闭连接
  • 它可以在分发连接之前对连接执行查询,如果出现错误,则丢弃连接并创建新连接。也可以在空闲时定期测试连接。
  • 您可以对将要创建的连接以及准备就绪的最小连接数设置限制。当然,限制在很大程度上取决于您的应用程序。
  • 我不知道如何,但 DBCP 知道何时没有关闭连接并为您关闭它,抛出异常以便您知道在看到日志时发生了什么。
  • DBCP 有一个非常有用的超时参数。如果池中的所有连接都在使用,它将等待一段时间以将连接返回到池中,如果达到限制时没有可用的连接,则会出现错误。

您可以通过使用最小连接数、要创建的最大连接数和超时来微调您的池。较长的超时将允许您拥有较低的连接限制,而较短的超时可能需要更大的连接数。这在很大程度上取决于您的应用程序做什么以及它如何使用连接。

于 2008-11-18T19:36:11.523 回答
2

我同意 matt b 的观点,即我们不应该重新发明轮子。

然而,根据这个这个问题的答案,使用 Commons DBCP 是有争议的。那里提到了更好的选择,例如c3poproxool

或者你可以使用 rdbms 依赖的连接池机制。

于 2009-02-09T11:58:29.893 回答
1

为什么要重新发明轮子?

有人可能已经解决了这个问题,而且更好。

如果您在 Java 世界中,您可以使用Commons DBCP

于 2008-11-07T04:04:50.460 回答