在DefaultMQProducerImpl.start()
中有一个MQClientInstance.start()
方法里面包含了大量定时任务何启动服务.
public void start() throws MQClientException {
PackageConflictDetect.detectFastjson();
synchronized (this) {
switch (this.serviceState) {
case CREATE_JUST:
this.serviceState = ServiceState.START_FAILED;
//1.如果没有namesrvAddr则去查找
if (null == this.clientConfig.getNamesrvAddr()) { this.clientConfig.setNamesrvAddr(this.mQClientAPIImpl.fetchNameServerAddr());
}
//2.启动client端远程通信,并获取当前客户端ip
this.mQClientAPIImpl.start();
//3.启动各种定时任务
this.startScheduledTask();
//4.启动拉去服务消息
this.pullMessageService.start();
//5.启动消费端负载均衡服务
this.rebalanceService.start();
this.defaultMQProducer.getDefaultMQProducerImpl().start(false);
log.info("the client factory [{}] start OK", this.clientId);
this.serviceState = ServiceState.RUNNING;
break;
case RUNNING:
break;
case SHUTDOWN_ALREADY:
break;
case START_FAILED:
throw new MQClientException("The Factory object[" + this.getClientId()
+ "] has been created before, and failed.", null);
default:
break;
}
}
}
fetchNameServerAddr()
关于namesrvAddr的设置一般在两个地方,还有一个是在环境变量里设置.如果这两个地方都没有设置会走该方法.
- 一个是在创建producer时候设置
producer.setNamesrvAddr(MyUtils.getNamesrvAddr())
- 另一个是在环境变量里设置
- 而
fetchNameServerAddr()
是第三种调用http接口去寻址.需配置hosts信息,客户端默认每隔两分钟去访问一次这个http地址,并更新本地namesrvAddr地址.
MQClientAPIImpl.start()
String localAddress = RemotingUtil.getLocalAddress();
projectGroupPrefix = this.getProjectGroupByIp(localAddress, 3000);
RemotingUtil.getLocalAddress()
方法通过 NetworkInterface.getNetworkInterfaces()
遍历解析,拿到当前客户端的ip地址.
this.getProjectGroupByIp(localAddress, 3000);
通过从nameserver拉取信息
startScheduledTask()启动各种定时任务
1.MQClientInstance.this.mQClientAPIImpl.fetchNameServerAddr()
如果当前客户端没有指定setNamesrvAddr,启动查找NamesrvAddr地址服务,每两分钟一次.
2. MQClientInstance.this.updateTopicRouteInfoFromNameServer()
启动从nameService更新topic路由信息服务
3. MQClientInstance.this.cleanOfflineBroker();
启动清理已经不存在的broker服务
MQClientInstance.this.sendHeartbeatToAllBrokerWithLock();
启动发送心跳服务
4. 启动consumer offset持久化
5. 启动调整消费线程池.
this.pullMessageService.start();与this.rebalanceService.start();都为consumer端服务,在consumer启动时候在进行分析.