2010-12-02 273 views
1

我有一個處理來自多個客戶端的登錄的java服務器。服務器爲每個tcp/ip套接字偵聽器創建一個線程。數據庫訪問由服務器創建的另一個線程處理。在java中實現異步消息隊列

目前,我已經連接到服務器的客戶端數量很低(< 100),所以我沒有真正的性能問題,但我正在研究如何在未來處理更多的客戶端。我擔心的是,有很多客戶端,我的服務器和數據庫線程會因客戶端線程對其方法的不斷調用而陷入困境。

具體來說就數據庫而言:目前每個客戶端線程都訪問其服務器父級上的公共數據庫線程並執行數據訪問方法。我認爲我應該做的是擁有某種客戶端線程可以將其數據請求放入其中的消息隊列,並且數據庫線程在接收到數據時將執行該消息隊列。如果有數據要從數據訪問調用中返回,那麼它可以將它放在隊列中供客戶端線程使用。所有這些都不會觸及主服務器代碼或任何其他客戶端線程。

因此,我認爲我想實現一個異步消息隊列,客戶端線程可以將消息放在上面,並且數據庫線程將從中取出。這是正確的方法嗎?任何想法和鏈接到我可以閱讀有關實施的地方,將不勝感激。

+0

不是一個答案,因此評論...你可能會想要Google上的「Java C10K問題」。基本上每個TCP/IP連接一個線程不會因爲您懷疑而削減它。你寫的問題不一定是*「constant calls」*,但是一旦客戶端數量變高(如果每個客戶端使用一個線程),就會在巨大數量的線程之間不停地交換數據。 – SyntaxT3rr0r 2010-12-02 14:43:16

回答

4

我不會推薦這種方法。

JMS出生於這樣的事情。它會比你從頭開始編寫的任何實現都要好。我建議使用內置了JMS的Java EE應用服務器,或者可以添加到像Tomcat這樣的servlet引擎的ActiveMQ或RabbitMQ。

我強烈建議您在編寫自己的作品之前調查一下。

1

您所描述的內容聽起來像是ExecutorCompletionService。這基本上是一個異步任務代理,它接受來自一個線程的請求(Runnable s或Callable s),以Future的形式返回即將到來的結果的「句柄」。該請求然後在thread pool(可能是single thread thread pool)中執行,然後將請求的結果通過Future傳遞迴調用線程。

在提交請求和提供響應之間,您的客戶端線程將簡單地等待Future(具有可選的超時)。

但是,如果您希望客戶端(因此客戶端線程)數量大幅增加,您應該評估一些Java NIO Server框架。這將允許您避免爲每個客戶端分配一個線程,尤其是因爲您希望所有這些線程花費一些時間來等待數據庫請求。如果是這種情況,我會建議看看MINANetty

乾杯。

//尼古拉斯

0

這聽起來像你想要做的是限制併發請求,要允許對數據庫的數量。 (要阻止它被超載)

我建議你有一個有限的連接池。當太多的線程想要使用數據庫時,它們將不得不等待連接空閒。一個簡單的方法是預先創建所有連接的BlockingQueue。

private final BlockingQueue<Connection> connections = new ArrayBlockingQueue<Connection>(40); { 
    // create connections 
} 

// to perform a query. 
Connection conn = connections.get(); 
try { 
    // do something 
} finally { 
    connections.add(conn); 
} 

這樣你就可以保持你的線程設計大同小異,並且限制併發查詢到數據庫的數量。通過一些調整,您可以根據需要創建連接,並在無法快速獲取數據庫連接時提供超時。