关于RabbitMQ的Channel默认线程(一个Connection控制线程数量)

前言

最近做了一个小功能,是通过一个客户端消费者监听队列消息, 代码如下:

Connection conn = getConnection();
Channel channel = conn.createChannel();
MessageConsumer consumer = ...
channel.basicConsume(realQueue, true, consumer);

通过jvm工具观察rabbitmq的线程使用情况,发现生产者每发一条消息,消费者这边就会创建一条线程,
言下之意,一个channel当消息来到时就会异步处理这些消息.

定位

通过断点查找发现原来是 ConsumerWorkService这个类控制的。
这个类顾名思义,就是消费者工作 ExecutorService, 这里的Service表示的是ExecutorService

这个类构造函数里有一个executor参数,当这个参数为空时,就会创建一个Executors.newFixedThreadPool,代码如下:

final public class ConsumerWorkService {
    private static final int MAX_RUNNABLE_BLOCK_SIZE = 16;
    private static final int DEFAULT_NUM_THREADS = Runtime.getRuntime().availableProcessors() * 2;
    private final ExecutorService executor;
    private final boolean privateExecutor;
    private final WorkPool workPool;
    private final int shutdownTimeout;

    public ConsumerWorkService(ExecutorService executor, ThreadFactory threadFactory, int queueingTimeout, int shutdownTimeout) {
        this.privateExecutor = (executor == null);
        this.executor = (executor == null) ? Executors.newFixedThreadPool(DEFAULT_NUM_THREADS, threadFactory)
                                           : executor;
        this.workPool = new WorkPool<>(queueingTimeout);
        this.shutdownTimeout = shutdownTimeout;
    }
  ...

默认的executor 会使用 CPU核数的2倍 作为线程池里线程的数量。

所以到底是要用多个channel,还是单个channel,这个就是其中一个参考依据。

这个executor又是怎么传进来的呢?

答案:

ConnectionFactory -> AMQConnection -> ChannelManager -> ConsumerWorkService

ConnectionFactory有一个属性是 shareExecutorService ,这个属性表示内部使用共享的唯一一个ExecutorService
设置这个属性就可以一直传到ConsumerWorkService中。

除了ConnectionFactory.setShareExecutorService方法以外,
还可以在Connection被创建时,设置executorService
ConnectionFactory的newConnection方法:

public Connection newConnection(ExecutorService executor) throws IOException, TimeoutException;

总结

通过设置shareExecutorService,无论多少个channel,都可以统一控制线程数量、队列数量,
根据实际情况进行配置。

你可能感兴趣的:(关于RabbitMQ的Channel默认线程(一个Connection控制线程数量))