Java 如何设计包含大量数据的JMS消息

Java 如何设计包含大量数据的JMS消息,java,database,jms,Java,Database,Jms,我正在设计一个系统,该系统使用ETL工具检索批量数据,即一个或多个表的插入/更新/删除,并将它们放在一个JMS主题上,稍后由多个客户机处理。现在,主题上的每条消息都代表一条记录I/U/D,我们有一条特殊的消息来分隔批处理的结尾。在单个事务中处理批处理很重要,因此用一个特殊的消息分隔一组消息并不理想:发布和接收消息的会话都必须针对多个消息进行设计;批定界符消息是一个混乱的解决方案(每次我们收到一条消息时,我们都需要检查它是否是最后一条消息),并且非常容易出错;系统调试和维护困难;关于这个主题的消息

我正在设计一个系统,该系统使用ETL工具检索批量数据,即一个或多个表的插入/更新/删除,并将它们放在一个JMS主题上,稍后由多个客户机处理。现在,主题上的每条消息都代表一条记录I/U/D,我们有一条特殊的消息来分隔批处理的结尾。在单个事务中处理批处理很重要,因此用一个特殊的消息分隔一组消息并不理想:发布和接收消息的会话都必须针对多个消息进行设计;批定界符消息是一个混乱的解决方案(每次我们收到一条消息时,我们都需要检查它是否是最后一条消息),并且非常容易出错;系统调试和维护困难;关于这个主题的消息数量很快变得巨大(高达数百万条)

现在,我认为改进体系结构的下一个自然步骤是将所有记录打包到一个JMS消息中,这样当接收到一个消息时,它包含一个事务,很容易检测到故障,在这个主题上没有“孤立”记录,等等。我只看到这样做的好处!下面是我的问题:

  • 创建这样一个打包消息的最佳方法是什么?我想我的选择是
    StreamMessage
    bytemmessage
    ObjectMessage
    。我排除了文本和映射消息,因为第一个消息需要文本解析,这会降低性能,我假设第二个消息似乎并不适合这种情况。我有点倾向于
    StreamMessage
    ,因为它看起来非常紧凑,尽管它需要大量的工作来编写自定义序列化代码(对于ByteMessage来说更糟)。不确定ObjectMessage,它是如何执行的?有现成的解决方案吗
  • 每条消息允许的最大大小是多少?它的大小可能是数百KB,甚至是几MB
谢谢你的想法

Giovanni

使用字节(例如ByteMessage)可能会占用更少的内存

如果您操作Java对象,您可以使用一个快速且字节有效的序列化/反序列化库,如


我们很乐意在消息传递系统的生产中使用Kryo,但是您有很多选择,例如流行的

而不是使用一条大消息,您可以使用两个(或更多)队列、相关ID和消息选择器

排队:

  • 将通知消息发布到“通知队列”以指示应开始处理
  • 将命令消息发布到“命令队列”,相关id设置为通知消息消息id(如果队列深度过高,可以使用多个命令队列)
  • 提交事务
  • 处理:

  • 从“通知队列”接收通知消息(例如,使用消息驱动bean)
  • 使用消息选择器接收和处理来自“命令队列”的所有相关消息
  • 提交事务

  • 您是否需要通过JMS传输所有数据(出于基础设施原因),或者您是否可以将所有数据放在具有给定batchID的DB表中,然后通过JMS发送该batchID,并让客户端从DB读取数据?不,所有内容都必须通过JMS。我的2美分:使用字节(例如BytemMessage)如果消息是Java的话,它可能是可以与快速且字节有效的序列化/反序列化库结合使用的内存占用较少的库objects@BGR我会调查的,谢谢@Giodude我会将我的评论作为一个答案,这样其他人就有机会轻松地对itSami进行评论,这是一个非常有趣的方法。干净多了。我一定会考虑的。唯一的问题是,它仍然需要跨多条消息的会话,并且数据仍然分为多个部分,这在某些情况下很容易出错。如果处理不正确,重新传递通知消息可能会导致一些问题。因此,通知消息应包含预期命令消息的数量。若收到的命令消息数不等于此数,则应回滚事务。另外,通知消息可能会在命令消息之后发送,如果事先不知道命令消息的数量(自己生成唯一的相关id并在通知消息中提供)Sami,这非常聪明。您将在何处存储预期的命令消息数?就在通知消息的正文中?谢谢你的帮助。是的,邮件正文是最好的地方。我会使用文本消息,因为它更容易处理(在解决生产中的错误时)只是一个小的更新:我们决定在一条消息中序列化一批数据,可能会使用Avro。为了补充这一点,我正在研究Avro()的序列化。与java序列化相比,它的性能非常好。