2017-02-03 22 views
0

我已經實現其接收網絡消息的簡單的Spring啓動應用程序,使用排隊成SingleChronicleQueue appender.writeText(STR),使用tailer.readText用於消息另一個線程輪詢() 。經過一些處理後,處理後的消息被放置在另一個SingleChronicleQueue中發送出去。 我在應用程序中有三個隊列。應用與紀事隊列存儲器不斷生長

應用旋轉每天晚上文件和第一奇怪的是,文件大小(每個Q)是相同的(不同的每一個Q)。 最大的cq4文件大約是每天220MB。

,我所面臨的問題是,在從開頭有三個天,直至現在內存從480MB增長到1.6GB,它只是不合理的。

我有我缺少一些組態一個概念,還是我的一個天真/壞實施。 (我應該在每次使用後都不關閉appender和tailer)。

這裏是一個剝離下來的例子,也許有人可以提供一些線索。

@Service 
public class QueuesService { 
    private static Logger LOG = LoggerFactory.getLogger(QueuesService.class); 

    @Autowired 
    AppConfiguration conf; 

    private SingleChronicleQueue Q = null; 
    private ExcerptAppender QAppender = null; 
    private ExcerptTailer QTailer = null; 

    public QueuesService() { 
    } 

    @PostConstruct 
    private void init() { 

     Q = SingleChronicleQueueBuilder.binary(conf.getQueuePath()).indexSpacing(1).build(); 
     QAppender = Q.acquireAppender(); 
     QTailer = Q.createTailer(); 
    } 

    public ExcerptAppender getQAppender() { 
     return QAppender; 
    } 

    public ExcerptTailer getQTailer() { 
     return QTailer; 
    } 
} 


@Service 
public class ProcessingService { 
    private static Logger LOG = LoggerFactory.getLogger(ProcessingService.class); 

    @Autowired 
    AppConfiguration conf; 

    @Autowired 
    private TaskExecutor taskExecutor; 

    @Autowired 
    private QueuesService queueService; 

    private QueueProcessor processor = null; 

    public ProcessingService() { 
    } 

    @PostConstruct 
    private void init() { 
     processor = new QueueProcessor(); 
     processor.start(); 
    } 

    @Override 
    public Message processMessage(Message msg, Map<String, Object> metadata) throws SomeException { 

     String strMsg = msg.getMessage().toString(); 

     if (LOG.isInfoEnabled()) { 
      LOG.info("\n" + strMsg); 
     } 

     try { 
      queueService.getQAppender().writeText(strMsg); 

      if (LOG.isInfoEnabled()) { 
       LOG.info("Added new message to queue. index: " + queueService.getQAppender().lastIndexAppended()); 
      } 
     } 
     catch(Exception e) { 
      LOG.error("Unkbown error. reason: " + e.getMessage(), e); 
     } 
    } 

    class QueueProcessor extends Thread { 

     public void run() { 
      while (!interrupted()) { 
       try { 
        String msg = queueService.getEpicQTailer().readText(); 

        if (msg != null) { 
         long index = queueService.getEpicQTailer().index(); 
         // process 
        } 
        else { 
         Thread.sleep(10); 
        } 
       } 
       catch (InterruptedException e) { 
        LOG.warn(e); 
        this.interrupt(); 
        break; 
       } 
      } 

      ThreadPoolTaskExecutor tp = (ThreadPoolTaskExecutor) taskExecutor; 
      tp.shutdown(); 
     } 
    } 
} 

回答

1

Chronicle Queue旨在使用虛擬內存,它可以比主內存(或堆)大得多,而不會對系統產生重大影響。這使您可以快速訪問數據。

這裏是一個處理在3小時內將1個寫入TB的一個例子。

enter image description here

https://vanilla-java.github.io/2017/01/27/Chronicle-Queue-storing-1-TB-in-virtual-memory-on-a-128-GB-machine.html

這表明它是如何慢得多得到作爲隊列增長

enter image description here

即使在它是1個TB大小的機器上128 GB,它在2秒內寫入1 GB相當一致。雖然這不會導致技術問題,但我們意識到這確實涉及到人們也會發現這種「怪異」,並且我們計劃有一種減少虛擬內存使用的模式(即使對於某些用途稍慢案例)

+0

喂佩特,非常感謝你的回答。只是澄清,每個週期後的隊列清除? –

+0

@GalNitzan它應該在一個循環之後(即當前和最後幾次)。如果它不是一個錯誤。有些人使用小時週期而不是每日週期。我更喜歡每天一個,但我可以理解人們想要每小時。 –

+0

好吧,實際上我想看到的是一些內存在午夜後被釋放,但我沒有看到內存消耗在不斷增長。我想我需要調試:(。謝謝你的答案。 –