我在下面的代码中做错什么了吗?或者,netty4组件是否存在一些已知的问题,即它的内存使用率很高?
我的问题是:
我使用Camel的netty4组件从套接字中流数据,聚合它,然后在它的途中发送它。
我尝试过许多不同的聚合数据的策略,似乎没有什么能帮助或损害内存的使用。
我的聚合周期为30秒,在这30秒内,数据总计约为1.3MB。
但是,我注意到我的内存使用量每30秒增加一次4MB。我在Linux中使用watch free -m来监控内存消耗。除了运行骆驼进程的终端之外,前台没有其他进程在运行。在运行Camel进程之前,内存的使用是完全稳定的(MB的规模没有波动)。
我已经使用了几乎所有的netty4设置,由Camel文档提供,这对我来说是显而易见的,而且似乎没有任何东西可以减少内存使用量。
我从命令行运行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开始生成额外的线程,但这些线程从未被清理过。在我的Java程序运行17个小时后,查看我的堆转储,我发现最大的违法者(类的实例数)分别是io.netty.util.Recycler$DefaultHandle和io.netty.channel.ChannelOutboundBuffer$Entry,分别占堆中类的20.2% (59,630)和19.8% (58,306)。
关于骆驼如何减轻这些设置,有什么想法吗?
发布于 2017-02-24 17:31:08
Java将要求尽可能多的内存,直到配置的限制。
即使当GC清除对象(只有在几乎满了时才会清除),它通常也不会将它声称的内存返回给操作系统。它将为将来的对象保留它拥有的malloc()d块。
因此,几乎所有正在创建大量新对象(即使它们是短暂的)的Java程序都会一直占用内存,直到堆达到-Xmx指定的大小为止。
Hotspot做自己的内存管理--也就是说,它malloc()的大块,并按自己的意愿使用它们,而不是每次创建对象时都执行malloc()。
因此,free并不是一个很好的工具来查看一个Java程序是否正在运行。
要查看JVM内存内部,可以使用诸如VisualVM之类的工具--然后可以查看堆大小、对象计数等。如果您的程序确实在泄漏内存,您将在这里看到它。
如果您希望您的Java程序使用更少的内存,请将-Xmx设置得更低,这将迫使GC在较小的内存分配中工作。
https://stackoverflow.com/questions/42439779
复制相似问题