我在下面的代码中做错了什么?或者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