Java - 将 JMS 消息流式传输到 Oracle 表中

Posted

技术标签:

【中文标题】Java - 将 JMS 消息流式传输到 Oracle 表中【英文标题】:Java - Streaming JMS messages into an Oracle table 【发布时间】:2017-04-03 14:03:39 【问题描述】:

我们正在使用 Spring Boot 和 JDBC 来捕获 JMS 消息并将它们保存到数据库表中。

为了尽可能减少内存占用,我们希望将这些消息流式传输到数据库中并批量提交。

是否可以将这些消息流式传输到数据库中?

目前,我们有多个 JMS 侦听器正在使用我们的 JMS 队列。这些侦听器共享一个 LinkedBlockingQueue(它由服务包装),他们将消息写入该队列。然后使用此队列,直到它耗尽,结果存储在列表中。这些结果使用 Spring 的 JdbcTemplate 进行持久化。

我们希望降低内存占用,因为这些消息存储在中间列表中只是为了允许批量保存。

在这种情况下有什么建议或经过验证的模式可以遵循吗?

【问题讨论】:

什么是事务边界?如果消息的消费是一个事务,那么结果似乎应该作为该事务的一部分被持久化。如果 JVM、网络等出现故障,如何恢复队列中的结果? 关于事务边界的要点。我认为更好的选择可能是一次使用一个消息列表,例如 2000 条消息,然后简单地保留它们而不添加任何花哨的批处理机制。事务边界位于侦听器级别。这样,我们仍然可以与已消费/未消费的内容保持一致。我看到只是将它们推送到队列会丢失交易信息。 【参考方案1】:

我设法使用方便的 StreamEx 库对流进行了分块。 但是,我们仍然在流实现时遇到 JVM 内存问题。我们需要运行一些进一步的性能和垃圾回收测试。

要流式传输的代码如下:

try (StreamEx<MyEntity> stream = StreamEx.of(myEntities)) 
            stream.groupRuns((prev, next) -> recordCounter.incrementAndGet() % myApplicationProperties.getBatchSize() != 0)
                    .forEach((chunk) -> 
                        if (chunk.size() != 1) 
                            jmsTemplate.convertAndSend(chunk);
                         else 
                            jmsTemplate.convertAndSend(chunk.get(0));
                        
                    );
        

【讨论】:

以上是关于Java - 将 JMS 消息流式传输到 Oracle 表中的主要内容,如果未能解决你的问题,请参考以下文章

理解JMS规范中消息的传输模式和消息持久化

破坏者还是 JMS?

JMS学习

使用 Java 将 JSON 流式传输到 BigQuery

消息中间之ActiveMQ

关于JMS和MQ