阅读须知
- 文章中使用/* */注释的方法会做深入分析
正文
Producer 的停止同样可以依托于 Spring bean 的生命周期,在 Spring bean 销毁时调用 DefaultMQProducer 的 shutdown 方法:
public void shutdown() {
/* 停止 Producer */
this.defaultMQProducerImpl.shutdown();
if (null != traceDispatcher) {
traceDispatcher.shutdown();
}
}
DefaultMQProducerImpl:
public void shutdown() {
this.shutdown(true);
}
DefaultMQProducerImpl:
public void shutdown(final boolean shutdownFactory) {
switch (this.serviceState) {
case CREATE_JUST:
break;
case RUNNING:
/* 注销 Producer */
this.mQClientFactory.unregisterProducer(this.defaultMQProducer.getProducerGroup());
// 停止异步发送线程池
this.defaultAsyncSenderExecutor.shutdown();
if (shutdownFactory) {
/* 停止 MQ 客户端实例 */
this.mQClientFactory.shutdown();
}
log.info("the producer [{}] shutdown OK", this.defaultMQProducer.getProducerGroup());
// 将状态置为已停止
this.serviceState = ServiceState.SHUTDOWN_ALREADY;
break;
case SHUTDOWN_ALREADY:
break;
default:
break;
}
}
MQClientInstance:
public void unregisterProducer(final String group) {
this.producerTable.remove(group);
/* 从 Broker 注销 Producer */
this.unregisterClientWithLock(group, null);
}
MQClientInstance:
private void unregisterClientWithLock(final String producerGroup, final String consumerGroup) {
try {
if (this.lockHeartbeat.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
try {
/* 注销 Producer 和 Consumer */
this.unregisterClient(producerGroup, consumerGroup);
} catch (Exception e) {
log.error("unregisterClient exception", e);
} finally {
this.lockHeartbeat.unlock();
}
} else {
log.warn("lock heartBeat, but failed.");
}
} catch (InterruptedException e) {
log.warn("unregisterClientWithLock exception", e);
}
}
这里我们看到虽然 consumerGroup 传入的值为 null,但是 Consumer 停止同样会复用这个流程。
MQClientInstance:
private void unregisterClient(final String producerGroup, final String consumerGroup) {
// 遍历 Broker 地址
Iterator<Entry<String, HashMap<Long, String>>> it = this.brokerAddrTable.entrySet().iterator();
while (it.hasNext()) {
Entry<String, HashMap<Long, String>> entry = it.next();
String brokerName = entry.getKey();
HashMap<Long, String> oneTable = entry.getValue();
if (oneTable != null) {
for (Map.Entry<Long, String> entry1 : oneTable.entrySet()) {
String addr = entry1.getValue();
if (addr != null) {
try {
/* 从 Broker 注销 Producer 和 Consumer */
this.mQClientAPIImpl.unregisterClient(addr, this.clientId, producerGroup, consumerGroup, 3000);
log.info("unregister client[Producer: {} Consumer: {}] from broker[{} {} {}] success", producerGroup, consumerGroup, brokerName, entry1.getKey(), addr);
} catch (RemotingException e) {
log.error("unregister client exception from broker: " + addr, e);
} catch (InterruptedException e) {
log.error("unregister client exception from broker: " + addr, e);
} catch (MQBrokerException e) {
log.error("unregister client exception from broker: " + addr, e);
}
}
}
}
}
}
MQClientAPIImpl:
public void unregisterClient(
final String addr,
final String clientID,
final String producerGroup,
final String consumerGroup,
final long timeoutMillis
) throws RemotingException, MQBrokerException, InterruptedException {
final UnregisterClientRequestHeader requestHeader = new UnregisterClientRequestHeader();
requestHeader.setClientID(clientID);
requestHeader.setProducerGroup(producerGroup);
requestHeader.setConsumerGroup(consumerGroup);
// 向 Broker 发送 UNREGISTER_CLIENT 命令
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UNREGISTER_CLIENT, requestHeader);
RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis);
assert response != null;
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
return;
}
default:
break;
}
throw new MQBrokerException(response.getCode(), response.getRemark());
}
这里 Broker 对应 UNREGISTER_CLIENT 命令的处理器为 ClientManageProcessor。从 Broker 注销 Producer 完成之后,最后就是停止客户端实例:
MQClientInstance:
public void shutdown() {
if (!this.consumerTable.isEmpty())
return;
if (!this.adminExtTable.isEmpty())
return;
if (this.producerTable.size() > 1)
return;
synchronized (this) {
switch (this.serviceState) {
case CREATE_JUST:
break;
case RUNNING:
this.defaultMQProducer.getDefaultMQProducerImpl().shutdown(false);
this.serviceState = ServiceState.SHUTDOWN_ALREADY;
// 停止拉取消息服务
this.pullMessageService.shutdown(true);
// 停止定时任务线程池
this.scheduledExecutorService.shutdown();
/* 停止远程调用客户端 */
this.mQClientAPIImpl.shutdown();
// 停止重新平衡服务
this.rebalanceService.shutdown();
if (this.datagramSocket != null) {
this.datagramSocket.close();
this.datagramSocket = null;
}
MQClientManager.getInstance().removeClientFactory(this.clientId);
log.info("the client factory [{}] shutdown OK", this.clientId);
break;
case SHUTDOWN_ALREADY:
break;
default:
break;
}
}
}
MQClientAPIImpl:
public void shutdown() {
this.remotingClient.shutdown();
}
NettyRemotingClient:
public void shutdown() {
try {
// 取消扫描和终止已弃用请求的定时任务
this.timer.cancel();
// 关闭所有远程调用的 channel
for (ChannelWrapper cw : this.channelTables.values()) {
this.closeChannel(null, cw.getChannel());
}
this.channelTables.clear();
// 关闭 netty 内部处理事件的线程组
this.eventLoopGroupWorker.shutdownGracefully();
// 关闭处理 netty 用户自定义事件的线程
if (this.nettyEventExecutor != null) {
this.nettyEventExecutor.shutdown();
}
// 关闭用于处理请求、响应、链接建立、断开等事件的线程池
if (this.defaultEventExecutorGroup != null) {
this.defaultEventExecutorGroup.shutdownGracefully();
}
} catch (Exception e) {
log.error("NettyRemotingClient shutdown exception, ", e);
}
// 关闭供处理器处理器请求的线程池
if (this.publicExecutor != null) {
try {
this.publicExecutor.shutdown();
} catch (Exception e) {
log.error("NettyRemotingServer shutdown exception, ", e);
}
}
}