如何修复奇怪的“ channelMax”错误rabbitmq rpc?

时间:2019-05-14 09:08:00

标签: spring rabbitmq spring-rabbitmq

我创建了简单的客户端和服务器。客户端发送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客户端似乎创建了太多渠道。如何解决? 为什么我的客户创造了那么多?

1 个答案:

答案 0 :(得分:1)

通道已缓存,因此通道的数量应与正在处理的实际RPC调用的数量一样。

您可能需要增加代理上的最大渠道设置。

编辑

如果您的RPC调用是长期的,则可以通过将AsyncRabbitTemplate与显式答复队列一起使用来减少使用通道的时间,并避免使用直接答复功能。

See the documentation

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");
    }

}