[英]Apache Camel Netty4 high memory usage
我在下面的代碼中做錯了嗎? 還是netty4組件存在一些已知問題,即它的內存使用率很高?
我的問題:
我正在使用Camel的netty4組件從套接字流傳輸數據,對其進行聚合,然后按其方式發送。
我嘗試了許多不同的策略來聚合數據,但似乎沒有任何方法可以幫助或損害內存使用。
我的匯總時間為30秒,在那30秒內數據總計約為1.3MB。
但是,我注意到我的內存使用量每30秒增加4MB 。 我在Linux中使用watch free -m
監視內存消耗。 除了運行Camel進程的終端之外,沒有其他進程在前台運行。 在運行Camel進程之前,內存使用情況完全穩定(MB規模沒有波動)。
我已經使用了Camel文檔提供的幾乎所有netty4設置,這對我來說很明顯,並且似乎沒有什么可以減少所使用的內存量。
我使用以下命令從命令行運行Camel實例
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並監視應用程序的運行,似乎Netty在發生類似Broken Pipe異常的事件時開始產生額外的線程,但是這些線程永遠都不會清除。 當查看我的Java程序運行17小時后的堆轉儲時,我發現最大的違規者(該類的實例數)是io.netty.util.Recycler$DefaultHandle
和io.netty.channel.ChannelOutboundBuffer$Entry
我的堆中的類分別為20.2%(59,630)和19.8%(58,306)。
關於駱駝如何減輕這些設置的任何想法?
Java將根據需要分配盡可能多的內存,直至達到配置的限制。
即使GC清除了對象(只有在幾乎滿時才會這樣做),它通常也不會將已占用的內存返回給OS。 它將保留其具有malloc()
d的塊以用於將來的對象。
因此,您會期望幾乎所有正在創建許多新對象(即使它們是短暫的)的Java程序都可以繼續聲明內存,直到其堆達到-Xmx
指定的大小為止。
熱點執行自己的內存管理-也就是說,它分配malloc()
的大塊,並按需要使用它們,而不是在每次創建對象時都進行malloc()
。
因此, free
不是查看Java程序自身行為的好工具。
要查看JVM內存內部,請使用VisualVM之類的工具-然后您可以查看堆的大小,對象數等。如果程序確實在泄漏內存,那么您將在這里看到它。
如果您希望Java程序使用較少的內存,請將-Xmx
設置為較低,這將強制GC在較小的內存分配中工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.