spirng+activemq消息重发配置

明确什么时候会引发消息重发机制
1.在使用事务的Session中,调用rollback()方法;
2.在使用事务的Session中,调用commit()方法之前就关闭了Session;
3.在Session中使用CLIENT_ACKNOWLEDGE签收模式或者INDIVIDUAL_ACKNOWLEDGE模式,并且调用了recover()方法。
可以通过设置ActiveMQConnectionFactory来定制想要的再次传送策略。
消息生产者关键配置
在第三方connectionFactory的bean中(在这里就是AmqConnectionFactory)加入这段配置

<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${brokerURL}"/>
        <property name="userName" value="admin"></property>
        <property name="password" value="admin"></property>
        <property name="redeliveryPolicy">
            <bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
                <!--是否在每次尝试重新发送失败后,增长这个等待时间 -->
                <property name="useExponentialBackOff" value="true"/>
                <!--重发次数,默认为6次   这里设置为1-->
                <property name="maximumRedeliveries" value="2"/>
                <!--重发时间间隔,默认为1-->
                <property name="initialRedeliveryDelay" value="1000"/>
                <!--第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value -->
                <property name="backOffMultiplier" value="2"/>
                <!--最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第二次重连时间间隔为 20ms,
                  第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。 -->
                <property name="maximumRedeliveryDelay" value="1000"/>
            </bean>
        </property>
    </bean>

消息消费者关键配置

<jms:listener-container connection-factory="connectionFactory"
                            destination-type="durableTopic"
                            acknowledge="client">
        <!--clientid+subcription的值为监听器注册到broker的名字-->
        <jms:listener destination="add.page.topic" ref="addPageMessageListener" subscription="add.Page"/>
        <jms:listener destination="del.page.topic" ref="delPageMessageListener" subscription="del.Page"/>
    </jms:listener-container>

关键配置是将应答模式设置成"client"!!!

消费者监听类关键代码
1.session.recover();调用此方法,消息才会重发
2.注意如果消费成功,一定要调用om.acknowledge();消息才会出队,防止消息堆积

public class AddPageMessageListener implements SessionAwareMessageListener<ObjectMessage> {

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Reference(timeout = 10000)
    private GoodsService goodsService;

    @Value("${staticUrl}")
    private String staticUrl;

    @Override
    public void onMessage(ObjectMessage om, Session session) throws JMSException {
        Long[] ids = (Long[]) om.getObject();
        Configuration configuration = freeMarkerConfigurer.getConfiguration();
        Template template = null;
        try {
            //引发异常
//            int i = 1/0;
            template = configuration.getTemplate("item.ftl");
            for (Long id : ids) {
                Map<String, Object> dataModel = goodsService.getGoodsByGoodsId(id);
                OutputStreamWriter outputStreamWriter =
                        new OutputStreamWriter(new FileOutputStream(staticUrl+id+".html"),"UTF-8");
                template.process(dataModel, outputStreamWriter);
                outputStreamWriter.close();
            }
            //必须应答,broker中的消息才会出队,相当于提交事务
            om.acknowledge();
        } catch (Exception e) {
            //调用recover方法,引发消息重发
            session.recover();
        }
    }
}

你可能感兴趣的:(java)