簡體   English   中英

Apache Camel Netty4高內存使用率

[英]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$DefaultHandleio.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM