如何设置连接池



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

  1. 您何时创建连接
  2. 你什么时候关闭连接,会关闭所有连接吗
  3. 你测试连接是否仍然良好。何时以及如何
  4. 如何计算最大连接数的一个好数字
  5. 您有什么样的监控来确保池中的用户行为良好?你能阻止一个坏代码把所有东西都取出来吗
  6. 你是否编写了自己的库,或者使用了第三方库

我认为这是一个不可知论的问题,但对特定数据库/语言的"特性"的评论是受欢迎的。例如,在某些数据库上连接可能比在其他数据库上连接更慢或更昂贵。

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

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

我使用了一个线程来监控池的几个方面,并使用了几个参数来控制它的行为。。。

  1. minimumInPool="3"。。。前三个是在发布时创建的。游泳池绝对不允许低于三个
  2. maximumIdleTimeBeforeRemovation="60"。。。如果一个连接空闲了一个小时,请将其删除并创建一个新连接。空闲时间可能意味着池中只有最少三个
  3. maximumInUseTimeBeforeRemovation="30"。。。如果一个给定的连接已经被检出超过30分钟,那么可能是出了问题。回想一下,然后终止连接
  4. maximumTimeBeforeRemoval="60"。。。如果超过60分钟,请将其取出
  5. maximumUsageBeforeRemoval="1000"。。。如果检出次数超过1000次,请将其移除
  6. monitorInterval="15"。。。每15分钟检查一次上述参数

这几年来对我很有帮助。我见过的最高的游泳池是151个连接。通常情况下,在大量使用期间,游泳池大约有十几个,而在凌晨,游泳池至少有三个闲置。

我使用了Oracle的JDBC精简驱动程序,并连接到了一个Oracle数据库。

以下是我在最近的实现中使用的基本原理。

  1. 在连接池中有两种类型的连接。第一个是现成的,意思是打开但未被客户端使用。第二种是活动的,意思是被客户使用。

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

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

  4. 当客户端以活动连接结束时,如果就绪连接少于M个,请将其返回到就绪状态。否则,请关闭它。这将阻止您拥有M个以上的就绪连接。

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

这样做的优点是在连接池中有足够的就绪年轻连接,而不会使服务器过载。

Jakarta Commons DBCP已经完成了您列出的所有工作:

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

您可以通过播放最小连接数、要创建的最大连接数和超时来微调池。超时时间越长,连接数越低,而超时时间越短,可能需要的连接数越大。这在很大程度上取决于应用程序的功能以及它如何使用连接。

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

然而,基于这个和这个问题的答案,使用Commons DBCP是有争议的。这里提到了更好的替代方案,比如c3po或proxyool。

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

我不确定您使用连接的上下文是什么,但我可以分享对我有用的内容。

我使用SQL服务器作为后端,并将缓存与之结合使用,以获得更好的性能。我的做法是,只有在我真正需要时才保持连接打开,而不是将连接池化,以便它们立即清理,我可以在SQL活动监视器中准确地看到哪些是活动的,哪些不是。每一个连接都会占用内存,所以在不需要它们的时候,让它发出沉闷的咆哮是很好的。

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

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

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

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

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

我的两分钱:

缓存您的数据!缓存您的数据!缓存您的数据!当你不能缓存数据时,尽可能少地访问数据库!

为什么要重新发明轮子?

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

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

相关内容

  • 没有找到相关文章

最新更新