Spring boot 使用事务会话时,使用Artemis和Spring JMS的消息分组不起作用

Spring boot 使用事务会话时,使用Artemis和Spring JMS的消息分组不起作用,spring-boot,jms,spring-jms,activemq-artemis,Spring Boot,Jms,Spring Jms,Activemq Artemis,消息分组似乎不起作用 在将字符串属性JMSXGroupID设置为'product=paper'之后,我的生产者应用程序通过JMS将消息发送到队列 我的producer应用程序发送另一条消息的方式与'product=paper'相同 在Artemis UI中浏览消息头时,我可以看到队列中的两条消息\u AMQ\u GROUP\u ID在这两个字段中的值均为'product=paper'JMSXGroupID不存在 当我调试使用SpringJMS的侦听器应用程序时,并发度为15-15(15 min

消息分组似乎不起作用

  • 在将字符串属性
    JMSXGroupID
    设置为
    'product=paper'
    之后,我的生产者应用程序通过JMS将消息发送到队列
  • 我的producer应用程序发送另一条消息的方式与
    'product=paper'
    相同
  • 在Artemis UI中浏览消息头时,我可以看到队列中的两条消息
    \u AMQ\u GROUP\u ID
    在这两个字段中的值均为
    'product=paper'
    <代码>JMSXGroupID不存在
  • 当我调试使用SpringJMS的侦听器应用程序时,并发度为15-15(15 min 15 max),我可以看到这两条消息都记录在不同的侦听器容器下。当我查看每个标题的映射时,
    \u AMQ\u GROUP\u ID
    不存在,
    JMSXGroupID
    的值为null,而不是
    'product=paper'
  • 为什么组id为的消息分组不起作用?这是否与Artemis没有将
    \u AMQ\u GROUP\u ID
    翻译回
    JMSXGroupID
    有关?或者SpringJMS没有将其多个使用者线程注册为不同的使用者,以便代理看到多个使用者

    编辑: 通过注释掉与使用容器工厂bean方法中的事务会话有关的行,我能够使消息分组在我的应用程序中工作。这似乎与使用事务性会话有关

    编辑2:

    下面是一个针对本地独立Artemis代理(版本2.10.1)并使用Spring Boot 2.2.0运行的自包含应用程序:

    GroupID应用程序(spring启动应用程序和bean):

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.reproduce</groupId>
        <artifactId>groupid</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>groupid</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-artemis</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
    4.0.0
    org.springframework.boot
    spring启动程序父级
    2.2.0.1发布
    复制
    用户组
    0.0.1-快照
    用户组
    SpringBoot的演示项目
    1.8
    org.springframework.boot
    弹簧靴起动器artemis
    com.fasterxml.jackson.datatype
    jackson-datatype-jsr310
    org.springframework.boot
    springbootmaven插件
    

    您可以看到,尽管所有这些消息都具有相同的组id,但它们被不同的侦听器容器线程记录。如果您从bean定义中注释掉事务管理器,它将重新开始工作。

    这都是关于消费者缓存的。默认情况下,当使用外部TXM时,将禁用缓存,以便在新的使用者上接收每条消息

    对于这个应用程序,你真的不需要事务管理器,
    sessiontransactited
    就足够了-容器将使用本地事务

    如果出于某种原因必须使用外部事务管理器,请考虑更改缓存级别。

    factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
    
    请参阅DMLC javadocs

    /**
     * Specify the level of caching that this listener container is allowed to apply.
     * <p>Default is {@link #CACHE_NONE} if an external transaction manager has been specified
     * (to reobtain all resources freshly within the scope of the external transaction),
     * and {@link #CACHE_CONSUMER} otherwise (operating with local JMS resources).
     * <p>Some Java EE servers only register their JMS resources with an ongoing XA
     * transaction in case of a freshly obtained JMS {@code Connection} and {@code Session},
     * which is why this listener container by default does not cache any of those.
     * However, depending on the rules of your server with respect to the caching
     * of transactional resources, consider switching this setting to at least
     * {@link #CACHE_CONNECTION} or {@link #CACHE_SESSION} even in conjunction with an
     * external transaction manager.
     * @see #CACHE_NONE
     * @see #CACHE_CONNECTION
     * @see #CACHE_SESSION
     * @see #CACHE_CONSUMER
     * @see #setCacheLevelName
     * @see #setTransactionManager
     */
    public void setCacheLevel(int cacheLevel) {
    
    /**
    *指定允许此侦听器容器应用的缓存级别。
    *如果已指定外部事务管理器,则默认值为{@link#CACHE_NONE}
    *(重新获得外部交易范围内的所有资源),
    *和{@link#CACHE_CONSUMER}否则(使用本地JMS资源操作)。
    *一些JavaEE服务器只向正在进行的XA注册其JMS资源
    *在新获得的JMS{@code Connection}和{@code Session}情况下的事务,
    *这就是为什么这个侦听器容器在默认情况下不缓存任何这些内容。
    *但是,这取决于服务器关于缓存的规则
    *事务性资源,考虑将此设置切换为至少
    *{@link#CACHE_CONNECTION}或{@link#CACHE_SESSION}甚至与
    *外部事务管理器。
    *@see#CACHE#u NONE
    *@see#CACHE_连接
    *@see#CACHE_SESSION
    *@see#CACHE#u消费者
    *@see#setCacheLevelName
    *@see#setTransactionManager
    */
    public void setCacheLevel(int cacheLevel){
    
    如果从用例中删除Spring JMS,只使用普通JMS
    MessageConsumer
    ,会发生什么?删除Spring JMS将表明问题是与Spring JMS有关还是与Artemis本身有关。请参阅。这是Artemis客户端中的一个bug(2.6.4);它适用于2.10.1。@GaryRussell我认为这是一个单独的问题。在同一个问题的示例中,您链接的组id实际起作用,只是标题中没有显示出来。您可以使用
    main()编写一个简单的Java应用程序
    method,订阅主题并多次运行该应用程序。幸好您添加了此注释;由于某些原因,我没有收到昨天的注释通知,并且这些注释不在我的回复历史记录中。我将查看并返回给您。完成了!谢谢。是否有好的文档帮助我理解tran您会推荐使用spring jms进行操作管理和缓存吗?这些配置对我来说仍然很神奇。我不知道除了javadocs和spring框架参考jms和事务章节之外还有什么。通常,如果您想要同步事务(例如DB和jms),您只需要插入事务管理器或者,如果您在托管容器(JEE)中运行,后者就是他们决定使用这些默认值的原因(当SpringJMS第一次创建时,JEE是常用的)。
    factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER);
    
    /**
     * Specify the level of caching that this listener container is allowed to apply.
     * <p>Default is {@link #CACHE_NONE} if an external transaction manager has been specified
     * (to reobtain all resources freshly within the scope of the external transaction),
     * and {@link #CACHE_CONSUMER} otherwise (operating with local JMS resources).
     * <p>Some Java EE servers only register their JMS resources with an ongoing XA
     * transaction in case of a freshly obtained JMS {@code Connection} and {@code Session},
     * which is why this listener container by default does not cache any of those.
     * However, depending on the rules of your server with respect to the caching
     * of transactional resources, consider switching this setting to at least
     * {@link #CACHE_CONNECTION} or {@link #CACHE_SESSION} even in conjunction with an
     * external transaction manager.
     * @see #CACHE_NONE
     * @see #CACHE_CONNECTION
     * @see #CACHE_SESSION
     * @see #CACHE_CONSUMER
     * @see #setCacheLevelName
     * @see #setTransactionManager
     */
    public void setCacheLevel(int cacheLevel) {