我在下面的代碼中做錯了什麼?或者netty4組件存在一些已知的問題,它只是有很高的內存使用率?Apache Camel Netty4高內存使用率
我的問題:
我使用駱駝的netty4組件從一個套接字流數據,彙總,然後把它的道路上。
我已經嘗試了很多不同的策略來聚合數據,沒有任何東西似乎幫助或傷害了內存使用。
我有30秒的聚合時間段,並且在那30秒內數據總計大約1.3MB。
但是,我注意到我的內存使用量每隔30秒增加4MB。我在Linux中使用watch free -m
來監視內存消耗。除了運行Camel進程的終端之外,沒有其他進程在前臺運行。內存使用情況在運行Camel進程之前是完全穩定的(MB的規模沒有波動)。
我已經玩過幾乎所有由Camel文檔提供的netty4設置,這對我來說很明顯,沒有什麼東西似乎減少了正在使用的內存量。
我從使用命令行運行駱駝實例
java -Xms200M -Xmx275M -Xss512k -Drolling_log_dir=/logs/ -jar myCamel.jar
我的路線:
from(netty4:tcp://localhost:12345?clientMode=true&textline=true).routeId(routeId + "A")
.log(LoggingLevel.INFO, rollingLogFile, "${body}")
.aggregate(constant(true), new StringAggregationStrategy(dataType))
.completionInterval(30000)
.to(fileUri);
from(fileUri).routeId(routeId + "B")
.process(doTheThing)
.to(pushFile)
.log("Transferred ${file:name} complete");
StringAggregationStrategy.java:
package com.aggregators;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.apache.camel.Exchange;
import org.apache.camel.processor.aggregate.AggregationStrategy;
public class StringAggregationStrategy implements AggregationStrategy {
private static Path tempFileDir;
public StringAggregationStrategy(String dataType){
tempFileDir = Paths.get("camelTempAggFileStorage/" + dataType + "/");
}
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
String newBody = newExchange.getIn().getBody(String.class);
String exchangeId;
Path tempAggFilePath;
if (!Files.exists(tempFileDir)){
try {
Files.createDirectories(tempFileDir);
} catch (IOException ex) {
ex.printStackTrace();
}
}
if (oldExchange == null){
cleanDirectory(tempFileDir);
exchangeId = newExchange.getExchangeId();
tempAggFilePath = Paths.get(tempFileDir.toString() + "/" + exchangeId + ".txt");
} else{
File oldFile = oldExchange.getIn().getBody(File.class);
tempAggFilePath = oldFile.toPath();
}
try (BufferedWriter writer = Files.newBufferedWriter(tempAggFilePath, StandardOpenOption.APPEND, StandardOpenOption.CREATE)){
if (oldExchange == null) {
writer.write(newBody);
newExchange.getIn().setBody(tempAggFilePath.toFile());
return newExchange;
} else {
writer.newLine();
writer.write(newBody);
oldExchange.getIn().setBody(tempAggFilePath.toFile());
return oldExchange;
}
} catch (IOException e) {
e.printStackTrace();
}
return oldExchange;
}
private void cleanDirectory(Path tempFileDir) {
for (File tempFile: tempFileDir.toFile().listFiles()){
if (!tempFile.isDirectory()){
tempFile.delete();
}
}
}
}
編輯:使用的VisualVM和監控這似乎是應用程序的繼續當發生Broken Pipe異常等情況時,Netty開始產生額外的線程,但這些線程永遠不會被清理。在我的Java程序運行17個小時後,當看到我的堆轉儲時,我看到最大的違規者(該類實例的數量)分別是io.netty.util.Recycler$DefaultHandle
和io.netty.channel.ChannelOutboundBuffer$Entry
,分別爲20.2%(59,630)和19.8%(58,306)分別在我的堆裏。
有關駱駝如何減輕這些設置的任何想法?
「我的記憶體使用量每30秒增加4MB。」 - 測量如何? – slim
啊對不起,我解釋了一切,但.. ..哈哈。除了使用Java進程的終端之外,我已經關閉了所有的東西,我正在看Linux中的'free -m'命令。在我運行該進程之前,內存處於穩定狀態,所以我不知道其他任何內容都在同時使用內存。我應該更新問題 – Jsmith
磁盤上的1.3MB可能會導致4MB的內存因爲壓縮而被加載到內存中。因此,每隔30秒將傳入的數據聚合到一個文件中,然後該文件將保存在內存中。內存增加的原因可能是該文件在處理完成時未從內存中刪除,或者GC只是在需要時才啓動。如果您只是將傳入數據附加到交換機構而不是創建文件,會發生什麼情況? – noMad17