Java 超时后重新发送消息

Java 超时后重新发送消息,java,rabbitmq,jms,spring-amqp,Java,Rabbitmq,Jms,Spring Amqp,我在SpringAMQP中有一个对象列表。对象来自控制器。有一个处理这些对象的服务。此服务可能会因OutOfMemoryException而崩溃。因此,我运行了几个应用程序实例 有一个问题:当服务崩溃时,我会丢失收到的消息。我读过关于NACK的书。并且可以在异常或运行时异常的情况下使用它。但是我的服务错误地崩溃了。因此,我无法发送NACK。是否可以在AMQP中设置超时,在此之后,如果我没有确认先前到达的消息,将再次发送消息 以下是我编写的代码: public class Exchanges {

我在SpringAMQP中有一个对象列表。对象来自控制器。有一个处理这些对象的服务。此服务可能会因OutOfMemoryException而崩溃。因此,我运行了几个应用程序实例

有一个问题:当服务崩溃时,我会丢失收到的消息。我读过关于NACK的书。并且可以在异常或运行时异常的情况下使用它。但是我的服务错误地崩溃了。因此,我无法发送NACK。是否可以在AMQP中设置超时,在此之后,如果我没有确认先前到达的消息,将再次发送消息

以下是我编写的代码:

public class Exchanges {
    public static final String EXC_RENDER_NAME = "render.exchange.topic";
    public static final TopicExchange EXC_RENDER = new TopicExchange(EXC_RENDER_NAME, true, false);
}

public class Queues {
    public static final String RENDER_NAME = "render.queue.topic";
    public static final Queue RENDER = new Queue(RENDER_NAME);
}

@RequiredArgsConstructor
@Service
public class RenderRabbitEventListener extends RabbitEventListener {
    private final ApplicationEventPublisher eventPublisher;

    @RabbitListener(bindings = @QueueBinding(value = @Queue(Queues.RENDER_NAME),
                                             exchange = @Exchange(value = Exchanges.EXC_RENDER_NAME, type = "topic"),
                                             key = "render.#")
    )
    public void onMessage(Message message, Channel channel) {
        String routingKey = parseRoutingKey(message);
        log.debug(String.format("Event %s", routingKey));
        RenderQueueObject queueObject = parseRender(message, RenderQueueObject.class);
        handleMessage(queueObject);
    }
    public void handleMessage(RenderQueueObject render) {
        GenericSpringEvent<RenderQueueObject> springEvent = new GenericSpringEvent<>(render);
        springEvent.setRender(true);
        eventPublisher.publishEvent(springEvent);
    }
}
公共类交换{
公共静态最终字符串EXC_RENDER_NAME=“RENDER.exchange.topic”;
public static final TopicExchange EXC_RENDER=新TopicExchange(EXC_RENDER_NAME,true,false);
}
公共类队列{
公共静态最终字符串RENDER_NAME=“RENDER.queue.topic”;
公共静态最终队列呈现=新队列(呈现名称);
}
@所需参数构造函数
@服务
公共类RenderRabbiteEventListener扩展了RabbitEventListener{
私有最终应用程序eventPublisher eventPublisher;
@RabbitListener(绑定=@QueueBinding(值=@Queue(Queues.RENDER_NAME)),
exchange=@exchange(value=Exchanges.EXC_RENDER_NAME,type=“topic”),
key=“render.#”)命令
)
公共消息无效(消息消息、通道){
字符串routingKey=parseRoutingKey(消息);
log.debug(String.format(“事件%s”,routingKey));
RenderQueueObject queueObject=parseRender(消息,RenderQueueObject.class);
handleMessage(队列对象);
}
公共无效handleMessage(RenderQueueObject render){
GenericSpringEvent springEvent=新的GenericSpringEvent(渲染);
setRender(true);
publishEvent(springEvent);
}
}
这就是发送消息的方法:

    @Async ("threadPoolTaskExecutor")
    @EventListener (condition = "# event.queue")
    public void start (GenericSpringEvent <RenderQueueObject> event) {
        RenderQueueObject renderQueueObject = event.getWhat ();
        send (RENDER_NAME, renderQueueObject);
}
private void send(String routingKey, Object queue) {
    try {
        rabbitTemplate.convertAndSend(routingKey, objectMapper.writeValueAsString(queue));
    } catch (JsonProcessingException e) {
        log.warn("Can't send event!", e);
    }
}
@Async(“threadPoolTaskExecutor”)
@EventListener(条件=“#event.queue”)
公共作废开始(GenericSpringEvent事件){
RenderQueueObject RenderQueueObject=event.getWhat();
send(RENDER_名称、renderQueueObject);
}
私有void发送(字符串路由密钥,对象队列){
试一试{
convertAndSend(routingKey,objectMapper.writeValueAsString(队列));
}捕获(JsonProcessingException e){
log.warn(“无法发送事件!”,e);
}
}

您需要关闭连接以使消息重新排队


最好在OOME之后终止应用程序(当然,这将关闭连接)。

Gary,是的,它可以工作。一旦连接关闭,消息就会复制到一个空闲实例。但是如果我异步运行,那么它就会停止工作。但是,正如我所说的,OOME应该被认为是致命的,你应该停止应用程序-你需要弄清楚为什么你会得到OOME。