本文分析PushConsumer的流量控制方法。PushConsumer使用Pull方式获取消息,好处是客户端能够根据自身的处理速度调整获取消息的操作速度。PushConsumer的流量控制采用多线程处理方式。
RocketMQ的版本为:4.2.0 release。
一.PushConsumer使用线程池,每个线程同时执行对应的消息处理逻辑
线程池的定义在 PushConsumer 启动的时候,初始化consumeMessageService的时候,在构造方法里面创建的。
DefaultMQPushConsumer#start
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"><span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">void</span></span> <span style="color:#e6db74"><span style="color:#a6e22e">start</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">(</span></span><span style="color:#f8f8f2"><span style="color:#f8f8f2">)</span></span> <span style="color:#66d9ef"><span style="color:#f92672">throws</span></span> MQClientException <span style="color:#f8f8f2">{</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>defaultMQPushConsumerImpl<span style="color:#f8f8f2">.</span><span style="color:#e6db74">start</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span></code></span></span>
DefaultMQPushConsumerImpl#start
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"><span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span><span style="color:#e6db74">getMessageListenerInner</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span> <span style="color:#66d9ef"><span style="color:#f92672">instanceof</span></span> MessageListenerOrderly<span style="color:#f8f8f2">)</span> <span style="color:#f8f8f2">{</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeOrderly <span style="color:#f8f8f2">=</span> <span style="color:#ae81ff"><span style="color:#f92672">true</span></span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeMessageService <span style="color:#f8f8f2">=</span>
<span style="color:#66d9ef"><span style="color:#f92672">new</span></span> ConsumeMessageOrderlyService<span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">,</span> <span style="color:#f8f8f2">(</span>MessageListenerOrderly<span style="color:#f8f8f2">)</span> <span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span><span style="color:#e6db74">getMessageListenerInner</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span> <span style="color:#66d9ef"><span style="color:#f92672">else</span></span> <span style="color:#66d9ef"><span style="color:#f92672">if</span></span> <span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span><span style="color:#e6db74">getMessageListenerInner</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span> <span style="color:#66d9ef"><span style="color:#f92672">instanceof</span></span> MessageListenerConcurrently<span style="color:#f8f8f2">)</span> <span style="color:#f8f8f2">{</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeOrderly <span style="color:#f8f8f2">=</span> <span style="color:#ae81ff"><span style="color:#f92672">false</span></span><span style="color:#f8f8f2">;</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeMessageService <span style="color:#f8f8f2">=</span>
<span style="color:#66d9ef"><span style="color:#f92672">new</span></span> ConsumeMessageConcurrentlyService<span style="color:#f8f8f2">(</span><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">,</span> <span style="color:#f8f8f2">(</span>MessageListenerConcurrently<span style="color:#f8f8f2">)</span> <span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span><span style="color:#e6db74">getMessageListenerInner</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span>
<span style="color:#f8f8f2">}</span></code></span></span>
ConsumeMessageOrderlyService#ConsumeMessageOrderlyService 构造方法 :
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"><span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeExecutor <span style="color:#f8f8f2">=</span> <span style="color:#66d9ef"><span style="color:#f92672">new</span></span> ThreadPoolExecutor<span style="color:#f8f8f2">(</span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>defaultMQPushConsumer<span style="color:#f8f8f2">.</span><span style="color:#e6db74">getConsumeThreadMin</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">,</span><span style="color:slategray"><span style="color:#75715e">// 线程池初始化时线程数量</span></span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>defaultMQPushConsumer<span style="color:#f8f8f2">.</span><span style="color:#e6db74">getConsumeThreadMax</span><span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">,</span><span style="color:slategray"><span style="color:#75715e">// 线程池最大线程数</span></span>
<span style="color:#ae81ff"><span style="color:#ae81ff">1000</span></span> <span style="color:#f8f8f2">*</span> <span style="color:#ae81ff"><span style="color:#ae81ff">60</span></span><span style="color:#f8f8f2">,</span>
TimeUnit<span style="color:#f8f8f2">.</span>MILLISECONDS<span style="color:#f8f8f2">,</span><span style="color:slategray"><span style="color:#75715e">// 线程保持活着的空闲时间,60秒</span></span>
<span style="color:#66d9ef"><span style="color:#f92672">this</span></span><span style="color:#f8f8f2">.</span>consumeRequestQueue<span style="color:#f8f8f2">,</span><span style="color:slategray"><span style="color:#75715e">// 排队等待线程队列</span></span>
<span style="color:#66d9ef"><span style="color:#f92672">new</span></span> ThreadFactoryImpl<span style="color:#f8f8f2">(</span><span style="color:#a6e22e"><span style="color:#e6db74">"ConsumeMessageThread_"</span></span><span style="color:#f8f8f2">)</span>
<span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">;</span></code></span></span>