我有一个数据库连接池。有消费者从该池中获取连接。 但我不相信那些消费者,因为很多消费者都没有回复我的联系。因此,游泳池挨饿,许多消费者也被迫等待无限。 例如:
class Consumer{
void someMethod(){
Connection con=Pool.getConnection();
//some bloody steps which throws exception
con.goodBye();//giving back the connection to the pool
}
}
由于异常并且可能因为傲慢而无法始终返回连接。我没有办法在消费者的课堂上限制Pool api的使用。
我怎样才能恢复连接?(我无法强迫消费者) 我相信没有万无一失的解决方案(可能我不是那么聪明)。任何人都可以提出一个非常好的解决方案。 我得到的一个解决方案是检查Consumer类中是否发生任何异常,如果发生Exception,则完全收回连接力。
或者是否有任何新的革命性DBPool设计模式在这种类型的典型场景中不是很受欢迎(尽管我认为我的情况非常通用,任何人都可能忘记将连接返回到池中。)
答案 0 :(得分:2)
这是糟糕的客户端代码。代码应该处理异常的情况并在完成时关闭连接。
但是,如果没有这样做,你无法从你的代码中知道。如果不这样做,那就是客户端代码的错误和问题。
有一个理智的超时是限制这种情况的唯一方法,但它最终仍然没有“解决”它。
-
您在评论中提到此池在多个客户端之间共享。当然,这会将责任转移给你。
您可以将每个客户端限制为仅使用一次X连接吗?这样,至少他们一次只能占用这么多。
否则,您可以为每个客户端创建单独的池。这种情况只会将问题移到堆栈中,但可能是合适的,具体取决于所涉及的物流。
答案 1 :(得分:1)
为什么不看看使用WeakReference
,在这里你可以调整你的代码以返回对连接的弱引用,当使用连接的线程死亡时,该对象将没有引用(除了你的WeakHashMap
),然后您可以定期识别这些对象并使用线程调用goodBye
方法。
here是一篇可以帮助您更好地理解这一点的文章。
.net也有一个WeakReference
类,其行为与此类似。
答案 2 :(得分:1)
不要返回连接对象,而是返回代表连接的代理对象。这些代理对象在最终确定时应该告别它们所代表的连接。如果代理未正确关闭,它最终将被垃圾收集,并在此时调整连接状态。
这里有两个问题。首先,GC之前的时间是不可预测的。比永远更好,但仍然可以很长。其次,要注意终结器中复杂调用的副作用,特别是对象复活。有一些罕见但丑陋的场景可以阻止对象的收集。
答案 3 :(得分:0)
您是否尝试捕获异常并关闭catch子句中的连接?
class Consumer{
void someMethod(){
Connection con=Pool.getConnection();
try{
//some bloody steps which throws exception
}catch(Exception e){
con.goodBye();
}
con.goodBye();//giving back the connection to the pool
}
}
编辑:您还可以使用finally
块删除冗余代码,并确保在每种情况下都关闭连接。我假设这是java代码,没有C#的经验。
答案 4 :(得分:0)
我能想到的唯一方法是不让消费者直接访问连接池,而是拥有自己的连接列表。然后在超时后回收连接,比如说60秒。