RabbitMQ服务器中存在一种行为,即当它达到水印值时它将不再接受后续连接/操作,直到它重新平衡自身为止。 当连接超时后发生这种情况时,RabbitMQ客户端优雅地获得超时,但我们正在使用Spring AMQP它继续挂起。
重现步骤
o创建RabbitMQ HA集群
o创建一个生成和使用消息的简单程序
o使RabbitMQ服务器在内存中达到高水位值,以便它不能接受任何新连接或执行任何操作,比如10分钟
o创建Q,从
发送消息Spring二进制版本
a)spring-rabbit-1.6.7.RELEASE.jar
b)spring-core-4.3.6.RELEASE.jar
c)spring-amqp-1.6.7.RELEASE.jar
我们尝试升级到Spring Rabbit和AMQP 2.0.2版本,但它没有帮助。
答案 0 :(得分:1)
您无法描述您的" RabbitMQ客户端"是,但java amqp-client
默认使用经典套接字。因此,您应该同时获得相同的行为(因为Spring AMQP使用该客户端)。也许你指的是其他语言客户端。
使用java Socket
s,当连接被阻止时,线程会被"卡住"在套接字写入中,它是不可中断的,也不会超时。
要处理这种情况,您必须使用the 4.0 client or above并使用NIO。
以下是演示该技术的示例应用程序。
@SpringBootApplication
public class So48699178Application {
private static Logger logger = LoggerFactory.getLogger(So48699178Application.class);
public static void main(String[] args) {
SpringApplication.run(So48699178Application.class, args);
}
@Bean
public ApplicationRunner runner(RabbitTemplate template, CachingConnectionFactory ccf) {
ConnectionFactory cf = ccf.getRabbitConnectionFactory();
NioParams nioParams = new NioParams();
nioParams.setWriteEnqueuingTimeoutInMs(20_000);
cf.setNioParams(nioParams);
cf.useNio();
return args -> {
Message message = MessageBuilder.withBody(new byte[100_000])
.andProperties(MessagePropertiesBuilder.newInstance()
.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT)
.build())
.build();
while (true) {
try {
template.send("foo", message);
}
catch (Exception e) {
logger.info(e.getMessage());
}
}
};
}
@Bean
public Queue foo() {
return new Queue("foo");
}
}
和
2018-02-09 12:00:29.803 INFO 9430 --- [main] com.example.So48699178Application:java.io.IOException:帧排队失败
2018-02-09 12:00:49.803 INFO 9430 --- [main] com.example.So48699178应用程序:java.io.IOException:帧排队失败
2018-02-09 12:01:09.807 INFO 9430 --- [main] com.example.So48699178应用程序:java.io.IOException:帧入队失败