Apache Camel Netty4高内存使用量



我在下面的代码中做错了吗?还是Netty4组件有一些已知的问题,其中它的内存使用量很高?

我的问题:

我正在使用骆驼的netty4组件从插座流式传输数据,然后将其汇总然后在途中发送。

我尝试了许多不同的策略来汇总数据,似乎没有任何帮助或伤害记忆使用情况。

我的聚合期为30秒,数据在30秒内总计约1.3MB。

但是,我注意到每30秒钟我的内存使用量增加了 4MB 。我正在Linux中使用watch free -m来监视内存消耗。前景中没有其他进程,除了骆驼过程运行的终端外。在运行骆驼过程之前,内存使用量完全稳定(MB的规模没有波动)。

我几乎使用了骆驼文档提供的每个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并监视应用程序的投入,似乎Netty在发生损坏的管道异常时开始产生额外的线程,但这些线程从未被清理。当我的Java程序运行17个小时后,看一下我的堆转储时,我看到最大的罪犯(班级数量)为io.netty.util.Recycler$DefaultHandleio.netty.channel.ChannelOutboundBuffer$Entry,分别为20.2%(59,630)(59,630)和19.8%(58,306)(58,306)(58,306)分别在我的堆中。

关于骆驼如何减轻这些设置的任何想法?

java将声称自己喜欢的内存,直到配置的限制。

即使GC清除了对象,只有在几乎满满的情况下才能做到这一点,通常也不会将其声称的内存返回给操作系统。它将保留其具有malloc() D的块。

因此,您希望几乎所有创建许多新对象的Java程序(即使它们是短暂的)都可以继续索取内存,直到其堆达到-Xmx指定的大小。

Hotspot执行自己的内存管理 - 也就是说,它是malloc()的大块,并按照自己的意愿使用它们,而不是每次创建对象时进行malloc()

因此,free不是查看Java程序是否表现自己的好工具。

要在JVM内存内看到诸如VisualVM之类的工具 - 然后您可以观看堆大小,对象计数等。如果您的程序确实在泄漏内存,您将在此处看到。

如果您希望Java程序使用较少的内存,请将-Xmx设置较低,这将迫使GC在较小的内存分配中工作。

最新更新