我创建了简单的客户端和服务器。客户端发送rpc请求:
RabbitTemplate template.convertSendAndReceive(...) ;
服务器收到它,并回答:
@RabbitListener(queues = "#{queue.getName()}")
public Object handler(@Payload String key)...
然后,我让客户端同时异步发送rpc请求(这会产生大量并发的rpc请求)。
意外收到错误:
org.springframework.amqp.AmqpResourceNotAvailableException:已达到channelMax限制。等会再试。 在org.springframework.amqp.rabbit.connection.SimpleConnection.createChannel(SimpleConnection.java:59) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory $ ChannelCachingConnectionProxy.createBareChannel(CachingConnectionFactory.java:1208) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory $ ChannelCachingConnectionProxy.access $ 200(CachingConnectionFactory.java:1196) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory.doCreateBareChannel(CachingConnectionFactory.java:599) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createBareChannel(CachingConnectionFactory.java:582) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory.getCachedChannelProxy(CachingConnectionFactory.java:552) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory.getChannel(CachingConnectionFactory.java:534) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory.access $ 1400(CachingConnectionFactory.java:99) 在org.springframework.amqp.rabbit.connection.CachingConnectionFactory $ ChannelCachingConnectionProxy.createChannel
Rabbitmq客户端似乎创建了太多渠道。如何解决? 为什么我的客户创造了那么多?
答案 0 :(得分:1)
通道已缓存,因此通道的数量应与正在处理的实际RPC调用的数量一样。
您可能需要增加代理上的最大渠道设置。
编辑
如果您的RPC调用是长期的,则可以通过将AsyncRabbitTemplate
与显式答复队列一起使用来减少使用通道的时间,并避免使用直接答复功能。
EDIT2
以下是使用AsyncRabbitTemplate
的示例;它在100个线程上发送1000条消息(而使用者有100个线程)。
用户使用的频道总数为107-100,仅发送了7个频道。
@SpringBootApplication
public class So56126654Application {
public static void main(String[] args) {
SpringApplication.run(So56126654Application.class, args);
}
@RabbitListener(queues = "so56126654", concurrency = "100")
public String slowService(String in) throws InterruptedException {
Thread.sleep(5_000L);
return in.toUpperCase();
}
@Bean
public ApplicationRunner runner(AsyncRabbitTemplate asyncTemplate) {
ExecutorService exec = Executors.newFixedThreadPool(100);
return args -> {
System.out.println(asyncTemplate.convertSendAndReceive("foo").get());
for (int i = 0; i < 1000; i++) {
int n = i;
exec.execute(() -> {
RabbitConverterFuture<Object> future = asyncTemplate.convertSendAndReceive("foo" + n);
try {
System.out.println(future.get(10, TimeUnit.SECONDS));
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
catch (TimeoutException e) {
e.printStackTrace();
}
});
}
};
}
@Bean
public AsyncRabbitTemplate asyncTemplate(ConnectionFactory connectionFactory) {
return new AsyncRabbitTemplate(connectionFactory, "", "so56126654", "so56126654-replies");
}
@Bean
public Queue queue() {
return new Queue("so56126654");
}
@Bean
public Queue reeplyQueue() {
return new Queue("so56126654-replies");
}
}