我怎样才能干净地关闭 Spring Rabbit 中的 RabbitTemplate?
How can I cleanly shut down a RabbitTemplate in Spring Rabbit?
我写了一个脚本,它使用 Spring Rabbit 使用 RabbitTemplate.convertAndSend 将大量消息放入 Rabbit 队列,然后退出。但是,即使在消息已入队后,Rabbit 连接似乎仍能使应用程序保持活动状态。我还没有找到一种方法来清楚地告诉 Rabbit 服务器在消息入队后停止。
我想出的最佳解决方案是将我的 convertAndSend 调用更改为 convertSendAndReceive,以便我知道消息已成功入队,然后使用 System.exit( 0).我切换到 convertSendAndReceive,因为 convertAndSend 似乎发生在后台线程或类似线程中,因为如果我在进行了多次这样的调用后执行 System.exit(0),只有前几个调用会成功。
请注意,仅创建 RabbitTemplate 不会导致此行为;通过 "send" 方法之一使用它。
下面的代码说明了这个问题。
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import static issues.RabbitSettings.*; //Static fields containing my test Rabbit connection info
public class RabbitTemplateShutdownIssue {
public static void main(String[] args) {
RabbitTemplate rabbitTemplate = createRabbitTemplate();
rabbitTemplate.convertAndSend(ROUTING_KEY, "Test"); // Or convertSendAndReceive
// The app never exits
}
private static RabbitTemplate createRabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
rabbitTemplate.setExchange(EXCHANGE);
rabbitTemplate.setMandatory(true);
return rabbitTemplate;
}
private static ConnectionFactory getConnectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOSTNAME);
connectionFactory.setPublisherConfirms(true);
connectionFactory.setVirtualHost(VIRTUAL_HOST);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
return connectionFactory;
}
}
有没有办法告诉 Rabbit 客户端关闭,理想情况下是在所有消息都已入队之后?
如果让 Spring 管理 beans,您可以在完成后 close()
应用程序上下文。
按照您现在的配置方式(没有 Spring 上下文),您可以在连接工厂上调用 destroy()
,一切都会关闭。
对这样的东西使用静态方法是一种反模式;您需要将工厂存储在一个静态字段中,这样您就可以销毁模板正在使用的那个。
您需要一个确认回调来确认 rabbit 已收到发送。
我写了一个脚本,它使用 Spring Rabbit 使用 RabbitTemplate.convertAndSend 将大量消息放入 Rabbit 队列,然后退出。但是,即使在消息已入队后,Rabbit 连接似乎仍能使应用程序保持活动状态。我还没有找到一种方法来清楚地告诉 Rabbit 服务器在消息入队后停止。
我想出的最佳解决方案是将我的 convertAndSend 调用更改为 convertSendAndReceive,以便我知道消息已成功入队,然后使用 System.exit( 0).我切换到 convertSendAndReceive,因为 convertAndSend 似乎发生在后台线程或类似线程中,因为如果我在进行了多次这样的调用后执行 System.exit(0),只有前几个调用会成功。
请注意,仅创建 RabbitTemplate 不会导致此行为;通过 "send" 方法之一使用它。
下面的代码说明了这个问题。
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import static issues.RabbitSettings.*; //Static fields containing my test Rabbit connection info
public class RabbitTemplateShutdownIssue {
public static void main(String[] args) {
RabbitTemplate rabbitTemplate = createRabbitTemplate();
rabbitTemplate.convertAndSend(ROUTING_KEY, "Test"); // Or convertSendAndReceive
// The app never exits
}
private static RabbitTemplate createRabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
rabbitTemplate.setExchange(EXCHANGE);
rabbitTemplate.setMandatory(true);
return rabbitTemplate;
}
private static ConnectionFactory getConnectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOSTNAME);
connectionFactory.setPublisherConfirms(true);
connectionFactory.setVirtualHost(VIRTUAL_HOST);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
return connectionFactory;
}
}
有没有办法告诉 Rabbit 客户端关闭,理想情况下是在所有消息都已入队之后?
如果让 Spring 管理 beans,您可以在完成后 close()
应用程序上下文。
按照您现在的配置方式(没有 Spring 上下文),您可以在连接工厂上调用 destroy()
,一切都会关闭。
对这样的东西使用静态方法是一种反模式;您需要将工厂存储在一个静态字段中,这样您就可以销毁模板正在使用的那个。
您需要一个确认回调来确认 rabbit 已收到发送。