2012-02-08 80 views
2

我有一個數據庫連接池。有消費者從該游泳池獲取連接。 但我不能相信這些消費者,因爲他們中的很多人都沒有返回我的連接。因此游泳池捱餓,許多消費者被迫等待無限。 例如:消費者沒有返回連接到我的數據庫連接池

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。 (我沒有辦法強制消費者) 我相信這裏沒有傻瓜證明的解決方案(可能不是那麼聰明)。任何人都可以想出一個很好的解決方案。 我得到的一個解決方案是檢查消費者類是否發生任何異常,如果發生異常,然後完全收回連接力。

或者是否有任何新的革命性DBPool設計模式在這種典型場景中不是非常流行(即使我認爲我的案例非常通用,任何人都可以忘記將連接還給池。 )

+2

這比編程更爲行政/管理問題。你無法解決世界上坐在隔間和編碼中的所有麻煩。對於這一個,我會編制一個可憐的程序客戶名單,並提出與他們的管理這個問題。 – 2012-02-08 13:31:28

回答

1

不要返回連接對象,而是返回代表連接的代理對象。這些代理對象最終確定後,應告別他們所代表的連接。如果代理未正確關閉,它最終將被垃圾回收,並在此時調整連接狀態。

這裏有兩個問題。首先,GC之前的時間是不可預測的。比永遠好,但仍然可以很長。其次,要注意終結器中複雜調用的副作用,特別是對象復活。有一些罕見但醜陋的場景阻止收集對象。

+0

我認爲這個解決方案是最不重要的 – Arshed 2012-02-09 06:54:32

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#的經驗。

+0

我同意你的意見。但不幸的是,消費者部分是由外部用戶實現的。我的意思是我提供了Pool API,並提供給消費者使用它。 – Arshed 2012-02-08 13:07:55

+1

@Arshed然後這不是你的責任。您已經提供了一個完善的api,消費者會故意忽略它。 – 2012-02-08 13:15:50

+0

案例就是這樣。有一個mysql(或任何DB)數據庫。這個mysql有'N'no數據庫。我有客戶/客戶。他們連接到他們各自的數據庫起訴我的游泳池。 Client1採取一些連接並永遠不會返回,不應該影響Client2。我同意,讓客戶1因爲他的罪而受苦。但爲什麼客戶端2 – Arshed 2012-02-08 13:19:50

0

我能想到的唯一方法不是讓消費者直接訪問連接池,而是擁有自己的連接列表。然後在超時後回收連接,例如60秒。

+0

我該怎麼做?當時消費者可能正在做一些交易,如果我這樣做會導致系統不穩定。 – Arshed 2012-02-08 13:11:11

+0

應該有一個超時,是的。但是,如果超時時間太短,您還會遇到其他問題。而且大多數連接池機制都不會「直接」暴露池,無論如何......這就是關鍵。 – 2012-02-08 13:12:31

+0

首先,您的系統此刻聽起來不穩定。如果消費者真正在建立關係超過一分鐘,您可能需要增加時間(我似乎記得谷歌強加30秒限制的一些事情)。 Pool.getConnection();在你的控制下?你會重新定義這個從列表中獲得連接,而不是直接從池中獲得連接。 – Jaydee 2012-02-08 13:48:54

2

這是糟糕的客戶端代碼。代碼應處理異常情況,並在完成時關閉連接。

雖然沒有辦法讓你從代碼中知道是否還沒有完成。這是客戶端代碼的錯誤和問題,如果它不這樣做。

有一個理智的超時是限制這種情況的唯一方法,但它最終還是不能「解決」它。

-

您在留言內提及,這池多個客戶端之間共享。當然,這將責任轉移回給你。

你可以限制每個客戶端只使用X連接嗎?這樣,至少他們一次只能綁定很多人。

否則,您可以爲每個客戶端創建單獨的池。這類問題只是將問題向下推進,但可能是合適的,具體取決於所涉及的物流。

+0

考慮這種情況。 我同意你的意見。該特定客戶端存在故障。但有n個客戶,如果1個客戶做錯了一些事情,它不應該影響其他客戶 – Arshed 2012-02-08 13:13:26

+0

我會編輯我的答案來反映。 – 2012-02-08 13:18:35

+0

我可以限制特定客戶端的連接數量。但它不能解決問題。單獨的獨立游泳池將解決問題。但我認爲它不實用。即使有太多的空閒連接(分配給其他客戶端),我也會限制允許連接到特定客戶端的連接數量。 – Arshed 2012-02-08 13:29:15

1

你爲什麼不看看使用WeakReference,在這裏你可以調整你的代碼來返回一個弱連接的連接,當線程使用連接死亡時,對象將沒有參考(除了你的WeakHashMap),您可以定期識別這些對象,並使用線程調用goodBye方法。

here是一篇文章,可以幫助您更好地理解這一點。

.net也有一個WeakReference類,其行爲非常類似於此。

+1

我懷疑這在這種情況下可能沒有幫助。它基本上實現了連接超時,但具有與通常使用的模式不同的模式。 – 2012-02-08 13:25:31

+0

是的,我同意,這裏的麻煩是當客戶不遵守標準,你仍然可以做一些事情來跟蹤事情..這是一種做法..我同意它的一個方式,但它在幾種情況下爲我工作。 – 2012-02-08 13:42:53

+1

我認爲這是一個好主意。謝謝 – Arshed 2012-02-08 13:52:36