2011-10-31 30 views
1

作爲標題,在我的模塊中,我有一個阻塞隊列來傳遞我的數據。服務器可以產生的數據是大量的日誌信息。爲了避免影響服務器的性能,我編寫了多線程客戶端來使用這些數據並將其保存在數據緩存中。由於數據可以每分鐘生成很多,所以我很困惑我應該初始化隊列的大小。而且我知道我可以設置我的隊列策略,即如果生成更多數據,我可以省略溢出部分。但是爲了儘可能多地保存這些數據,我在隊列中創建了多少個大小。如何估計或計算ArrayBlockingQueue的大小

您能否給我一些建議?據我所知,它與我的服務器JVM堆棧大小&有關,我的JVM中的單一日誌記錄數據?

+0

這聽起來像你想弄清楚設置隊列的大小。這是一個準確的陳述嗎? –

+0

據我所知,在我的代碼在服務器上運行之前,無論是壓力測試還是模塊測試,我都需要知道近似值。我在多線程程序中很弱,是否有一種準確或近似的語句估計它? –

回答

2

使其「儘可能大是合理的」。例如,如果你可以使用1Gb的內存,那麼分配它的大小爲1Gb,除以隊列中對象的平均字節數。

如果我不得不選擇一個「合理」的號碼,我會從10000開始。原因是,如果它增長到比這更大,那麼增大它並不是一個好主意,並且不會有太大幫助,因爲顯然日誌記錄要求超過了你的日誌記錄能力,所以是時候退出客戶端。

「調整」通過實驗通常是最好的方法,因爲它依賴於應用程序的配置文件:

  • 如果有高點和低點在應用程序的活動,那麼較大的隊列將幫助「平穩out「你服務器上的負載
  • 如果你的應用程序有一個相對穩定的負載,那麼較小的隊列是適當的,因爲只有一個較大的隊列延遲當客戶端被阻止時的不可避免的一點 - 你最好把它做得更小,將更多資源(更多的日誌記錄線程)用於消耗工作。

還要注意的是一個非常大的隊列可能影響垃圾收集的響應,以釋放內存,因爲它要遍歷一個更大的堆(隊列中的所有對象),每次運行時,兩個增加負荷CPU和內存。

您希望儘可能縮小尺寸,而不會影響吞吐量和響應速度。爲了評估這一點,你需要建立一個測試服務器,並用一個典型的負載來查看發生了什麼。請注意,您可能需要從多臺計算機上獲取它才能在服務器上實現負載,因爲從一臺計算機上啓動它可以限制由於測試客戶端計算機上的CPU核心和其他資源數量而造成的負載。

說實話,我只是做了大小10000和調整工作線程的數量,而不是隊列大小。

+0

感謝您的回答。我同意您的建議。因此,該語句可能是「隊列大小=堆棧內存大小/對象的平均字節數」。然後提出另一個問題。如何計算JVM中的對象字節?並且您知道嗎如何在運行時環境中監控這個隊列?運行時打印它的大小? –

+0

@Bobby查看更新的答案。 – Bohemian

+0

感謝您再次分享您的知識基礎。現在我有了一些想法來繼續如何測試和調整它。 –

2

連續寫入磁盤相當快(每秒容易20MB)。而不是將數據存儲在RAM中,您最好將其寫入磁盤而不必擔心內存需求。您的客戶可以從文件而不是RAM中讀取數據。

要知道java對象的大小,可以使用任何java分析器。 YourKit是我的最愛。

我認爲真正的問題並不是隊列的大小,而是當事情超出你的計劃容量時你想要做什麼。 ArrayBlockingQueue會簡單地阻止你的線程,這可能或不可能是正確的。您的選項通常是:

1)根據爲此提交的內存阻塞線程(使用ArrayBlockingQueue) 2)將錯誤返回到「上方圖層」,並讓該圖層決定要做什麼......可能會發送錯誤到客戶端 3)你可以扔掉一些數據...說,這是很久以前排隊。 4)一旦你溢出RAM容量,開始寫入磁盤。