rocketmq源码解析broker启动④

说在前面

 

源码解析

进入方法,构建索引,org.apache.rocketmq.store.index.IndexService#buildIndex

  public void buildIndex(DispatchRequest req) {//        试着获取并创建索引文件        IndexFile indexFile = retryGetAndCreateIndexFile();        if (indexFile != null) {            long endPhyOffset = indexFile.getEndPhyOffset();            DispatchRequest msg = req;            String topic = msg.getTopic();            String keys = msg.getKeys();            if (msg.getCommitLogOffset() < endPhyOffset) {                return;            }
//            解析事务消息类型=》            final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag());            switch (tranType) {                case MessageSysFlag.TRANSACTION_NOT_TYPE:                case MessageSysFlag.TRANSACTION_PREPARED_TYPE:                case MessageSysFlag.TRANSACTION_COMMIT_TYPE:                    break;                case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE:                    return;            }
            if (req.getUniqKey() != null) {                indexFile = putKey(indexFile, msg, buildKey(topic, req.getUniqKey()));                if (indexFile == null) {                    log.error("putKey error commitlog {} uniqkey {}", req.getCommitLogOffset(), req.getUniqKey());                    return;                }            }
            if (keys != null && keys.length() > 0) {                String[] keyset = keys.split(MessageConst.KEY_SEPARATOR);                for (int i = 0; i < keyset.length; i++) {                    String key = keyset[i];                    if (key.length() > 0) {                        indexFile = putKey(indexFile, msg, buildKey(topic, key));                        if (indexFile == null) {                            log.error("putKey error commitlog {} uniqkey {}", req.getCommitLogOffset(), req.getUniqKey());                            return;                        }                    }                }            }        } else {            log.error("build index error, stop building index");        }    }

返回方法,消息到达通知监听器,org.apache.rocketmq.broker.longpolling.NotifyMessageArrivingListener#arriving

  @Override    public void arriving(String topic, int queueId, long logicOffset, long tagsCode,        long msgStoreTime, byte[] filterBitMap, Map<String, String> properties) {//        =》        this.pullRequestHoldService.notifyMessageArriving(topic, queueId, logicOffset, tagsCode,            msgStoreTime, filterBitMap, properties);    }

进入方法,org.apache.rocketmq.broker.longpolling.PullRequestHoldService#notifyMessageArriving(java.lang.String, int, long, java.lang.Long, long, byte[], java.util.Map<java.lang.String,java.lang.String>)

   public void notifyMessageArriving(final String topic, final int queueId, final long maxOffset, final Long tagsCode,        long msgStoreTime, byte[] filterBitMap, Map<String, String> properties) {        String key = this.buildKey(topic, queueId);//        获取pullRequest        ManyPullRequest mpr = this.pullRequestTable.get(key);        if (mpr != null) {            List<PullRequest> requestList = mpr.cloneListAndClear();            if (requestList != null) {                List<PullRequest> replayList = new ArrayList<PullRequest>();
                for (PullRequest request : requestList) {                    long newestOffset = maxOffset;                    if (newestOffset <= request.getPullFromThisOffset()) {//                        按topic, queueId从消息队列中获取最大offset=》                        newestOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId);                    }
                    if (newestOffset > request.getPullFromThisOffset()) {                        boolean match = request.getMessageFilter().isMatchedByConsumeQueue(tagsCode,                            new ConsumeQueueExt.CqExtUnit(tagsCode, msgStoreTime, filterBitMap));                        // match by bit map, need eval again when properties is not null.                        if (match && properties != null) {                            match = request.getMessageFilter().isMatchedByCommitLog(null, properties);                        }
                        if (match) {                            try {//                                执行pull request请求=》                                this.brokerController.getPullMessageProcessor().executeRequestWhenWakeup(request.getClientChannel(),                                    request.getRequestCommand());                            } catch (Throwable e) {                                log.error("execute request when wakeup failed.", e);                            }                            continue;                        }                    }
                    if (System.currentTimeMillis() >= (request.getSuspendTimestamp() + request.getTimeoutMillis())) {                        try {//                            =》                            this.brokerController.getPullMessageProcessor().executeRequestWhenWakeup(request.getClientChannel(),                                request.getRequestCommand());                        } catch (Throwable e) {                            log.error("execute request when wakeup failed.", e);                        }                        continue;                    }
                    replayList.add(request);                }
                if (!replayList.isEmpty()) {                    mpr.addPullRequest(replayList);                }            }        }    }

进入方法,按topic, queueId从消息队列中获取最大offset,org.apache.rocketmq.store.DefaultMessageStore#getMaxOffsetInQueue介绍过了。

返回方法,执行pull request请求,org.apache.rocketmq.broker.processor.PullMessageProcessor#executeRequestWhenWakeup

 public void executeRequestWhenWakeup(final Channel channel,        final RemotingCommand request) throws RemotingCommandException {        Runnable run = new Runnable() {            @Override            public void run() {                try {//                    =》                    final RemotingCommand response = PullMessageProcessor.this.processRequest(channel, request, false);
                    if (response != null) {                        response.setOpaque(request.getOpaque());                        response.markResponseType();                        try {                            channel.writeAndFlush(response).addListener(new ChannelFutureListener() {                                @Override                                public void operationComplete(ChannelFuture future) throws Exception {                                    if (!future.isSuccess()) {                                        log.error("processRequestWrapper response to {} failed",                                            future.channel().remoteAddress(), future.cause());                                        log.error(request.toString());                                        log.error(response.toString());                                    }                                }                            });                        } catch (Throwable e) {                            log.error("processRequestWrapper process request over, but response failed", e);                            log.error(request.toString());                            log.error(response.toString());                        }                    }                } catch (RemotingCommandException e1) {                    log.error("excuteRequestWhenWakeup run", e1);                }            }        };//        异步执行        this.brokerController.getPullMessageExecutor().submit(new RequestTask(run, channel, request));    }

进入方法,org.apache.rocketmq.broker.processor.PullMessageProcessor#processRequest(io.netty.channel.Channel, org.apache.rocketmq.remoting.protocol.RemotingCommand, boolean)介绍过了。

返回方法,ha服务启动,org.apache.rocketmq.store.ha.HAService#start

 public void start() throws Exception {//        建立nio连接,为什么不用netty呢        this.acceptSocketService.beginAccept();//        服务启动=》        this.acceptSocketService.start();        this.groupTransferService.start();//        ha client启动=》        this.haClient.start();    }

进入方法,建立nio连接,为什么不用netty呢,

org.apache.rocketmq.store.ha.HAService.AcceptSocketService#beginAccept

public void beginAccept() throws Exception {            this.serverSocketChannel = ServerSocketChannel.open();            this.selector = RemotingUtil.openSelector();            this.serverSocketChannel.socket().setReuseAddress(true);            this.serverSocketChannel.socket().bind(this.socketAddressListen);            this.serverSocketChannel.configureBlocking(false);            this.serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);        }

返回方法,服务启动,org.apache.rocketmq.store.ha.HAService.AcceptSocketService#run

   @Override        public void run() {            log.info(this.getServiceName() + " service started");
            while (!this.isStopped()) {                try {                    this.selector.select(1000);                    Set<SelectionKey> selected = this.selector.selectedKeys();
                    if (selected != null) {                        for (SelectionKey k : selected) {                            if ((k.readyOps() & SelectionKey.OP_ACCEPT) != 0) {                                SocketChannel sc = ((ServerSocketChannel) k.channel()).accept();
                                if (sc != null) {                                    HAService.log.info("HAService receive new connection, "                                        + sc.socket().getRemoteSocketAddress());
                                    try {                                        HAConnection conn = new HAConnection(HAService.this, sc);//                                        ha connection启动                                        conn.start();                                        HAService.this.addConnection(conn);                                    } catch (Exception e) {                                        log.error("new HAConnection exception", e);                                        sc.close();                                    }                                }                            } else {                                log.warn("Unexpected ops in select " + k.readyOps());                            }                        }
                        selected.clear();                    }                } catch (Exception e) {                    log.error(this.getServiceName() + " service has exception.", e);                }            }
            log.info(this.getServiceName() + " service end");        }

进入方法,ha connection启动,org.apache.rocketmq.store.ha.HAConnection#start

   public void start() {        this.readSocketService.start();        this.writeSocketService.start();    }

进入方法,org.apache.rocketmq.store.ha.HAConnection.ReadSocketService#run

   @Override        public void run() {            HAConnection.log.info(this.getServiceName() + " service started");
            while (!this.isStopped()) {                try {                    this.selector.select(1000);//                    处理读事件=》                    boolean ok = this.processReadEvent();                    if (!ok) {                        HAConnection.log.error("processReadEvent error");                        break;                    }
                    long interval = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now() - this.lastReadTimestamp;                    if (interval > HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig().getHaHousekeepingInterval()) {                        log.warn("ha housekeeping, found this connection[" + HAConnection.this.clientAddr + "] expired, " + interval);                        break;                    }                } catch (Exception e) {                    HAConnection.log.error(this.getServiceName() + " service has exception.", e);                    break;                }            }
            this.makeStop();
            writeSocketService.makeStop();
            haService.removeConnection(HAConnection.this);
            HAConnection.this.haService.getConnectionCount().decrementAndGet();
            SelectionKey sk = this.socketChannel.keyFor(this.selector);            if (sk != null) {                sk.cancel();            }
            try {                this.selector.close();                this.socketChannel.close();            } catch (IOException e) {                HAConnection.log.error("", e);            }
            HAConnection.log.info(this.getServiceName() + " service end");        }

进入方法,处理读事件,org.apache.rocketmq.store.ha.HAConnection.ReadSocketService#processReadEvent

 private boolean processReadEvent() {            int readSizeZeroTimes = 0;
            if (!this.byteBufferRead.hasRemaining()) {                this.byteBufferRead.flip();                this.processPostion = 0;            }
            while (this.byteBufferRead.hasRemaining()) {                try {                    int readSize = this.socketChannel.read(this.byteBufferRead);                    if (readSize > 0) {                        readSizeZeroTimes = 0;                        this.lastReadTimestamp = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now();                        if ((this.byteBufferRead.position() - this.processPostion) >= 8) {                            int pos = this.byteBufferRead.position() - (this.byteBufferRead.position() % 8);                            long readOffset = this.byteBufferRead.getLong(pos - 8);                            this.processPostion = pos;
                            HAConnection.this.slaveAckOffset = readOffset;                            if (HAConnection.this.slaveRequestOffset < 0) {                                HAConnection.this.slaveRequestOffset = readOffset;                                log.info("slave[" + HAConnection.this.clientAddr + "] request offset " + readOffset);                            }
                            HAConnection.this.haService.notifyTransferSome(HAConnection.this.slaveAckOffset);                        }                    } else if (readSize == 0) {                        if (++readSizeZeroTimes >= 3) {                            break;                        }                    } else {                        log.error("read socket[" + HAConnection.this.clientAddr + "] < 0");                        return false;                    }                } catch (IOException e) {                    log.error("processReadEvent exception", e);                    return false;                }            }
            return true;        }

进入方法,org.apache.rocketmq.store.ha.HAConnection.ReadSocketService#run

   @Override        public void run() {            HAConnection.log.info(this.getServiceName() + " service started");
            while (!this.isStopped()) {                try {                    this.selector.select(1000);//                    处理读事件=》                    boolean ok = this.processReadEvent();                    if (!ok) {                        HAConnection.log.error("processReadEvent error");                        break;                    }
                    long interval = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now() - this.lastReadTimestamp;                    if (interval > HAConnection.this.haService.getDefaultMessageStore().getMessageStoreConfig().getHaHousekeepingInterval()) {                        log.warn("ha housekeeping, found this connection[" + HAConnection.this.clientAddr + "] expired, " + interval);                        break;                    }                } catch (Exception e) {                    HAConnection.log.error(this.getServiceName() + " service has exception.", e);                    break;                }            }
            this.makeStop();
            writeSocketService.makeStop();
            haService.removeConnection(HAConnection.this);
            HAConnection.this.haService.getConnectionCount().decrementAndGet();
            SelectionKey sk = this.socketChannel.keyFor(this.selector);            if (sk != null) {                sk.cancel();            }
            try {                this.selector.close();                this.socketChannel.close();            } catch (IOException e) {                HAConnection.log.error("", e);            }
            HAConnection.log.info(this.getServiceName() + " service end");        }

进入方法,处理读事件,org.apache.rocketmq.store.ha.HAConnection.ReadSocketService#processReadEvent

 private boolean processReadEvent() {            int readSizeZeroTimes = 0;
            if (!this.byteBufferRead.hasRemaining()) {                this.byteBufferRead.flip();                this.processPostion = 0;            }
            while (this.byteBufferRead.hasRemaining()) {                try {                    int readSize = this.socketChannel.read(this.byteBufferRead);                    if (readSize > 0) {                        readSizeZeroTimes = 0;                        this.lastReadTimestamp = HAConnection.this.haService.getDefaultMessageStore().getSystemClock().now();                        if ((this.byteBufferRead.position() - this.processPostion) >= 8) {                            int pos = this.byteBufferRead.position() - (this.byteBufferRead.position() % 8);                            long readOffset = this.byteBufferRead.getLong(pos - 8);                            this.processPostion = pos;
                            HAConnection.this.slaveAckOffset = readOffset;                            if (HAConnection.this.slaveRequestOffset < 0) {                                HAConnection.this.slaveRequestOffset = readOffset;                                log.info("slave[" + HAConnection.this.clientAddr + "] request offset " + readOffset);                            }
                            HAConnection.this.haService.notifyTransferSome(HAConnection.this.slaveAckOffset);                        }                    } else if (readSize == 0) {                        if (++readSizeZeroTimes >= 3) {                            break;                        }                    } else {                        log.error("read socket[" + HAConnection.this.clientAddr + "] < 0");                        return false;                    }                } catch (IOException e) {                    log.error("processReadEvent exception", e);                    return false;                }            }
            return true;        }

进入方法,org.apache.rocketmq.store.ha.HAService.GroupTransferService#run

  public void run() {            log.info(this.getServiceName() + " service started");
            while (!this.isStopped()) {                try {                    this.waitForRunning(10);                    this.doWaitTransfer();                } catch (Exception e) {                    log.warn(this.getServiceName() + " service has exception. ", e);                }            }
            log.info(this.getServiceName() + " service end");        }

进入方法,org.apache.rocketmq.store.ha.HAService.GroupTransferService#doWaitTransfer

 private void doWaitTransfer() {            synchronized (this.requestsRead) {                if (!this.requestsRead.isEmpty()) {                    for (CommitLog.GroupCommitRequest req : this.requestsRead) {                        boolean transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset();                        for (int i = 0; !transferOK && i < 5; i++) {                            this.notifyTransferObject.waitForRunning(1000);                            transferOK = HAService.this.push2SlaveMaxOffset.get() >= req.getNextOffset();                        }
                        if (!transferOK) {                            log.warn("transfer messsage to slave timeout, " + req.getNextOffset());                        }
                        req.wakeupCustomer(transferOK);                    }
                    this.requestsRead.clear();                }            }        }

返回方法,ha client启动,org.apache.rocketmq.store.ha.HAService.HAClient#run

  @Override        public void run() {            log.info(this.getServiceName() + " service started");
            while (!this.isStopped()) {                try {//                    连接master=》                    if (this.connectMaster()) {
                        if (this.isTimeToReportOffset()) {                            boolean result = this.reportSlaveMaxOffset(this.currentReportedOffset);                            if (!result) {//                                关闭master=》                                this.closeMaster();                            }                        }
                        this.selector.select(1000);
//                        处理读事件=》                        boolean ok = this.processReadEvent();                        if (!ok) {                            this.closeMaster();                        }
                        if (!reportSlaveMaxOffsetPlus()) {                            continue;                        }
                        long interval =                            HAService.this.getDefaultMessageStore().getSystemClock().now()                                - this.lastWriteTimestamp;                        if (interval > HAService.this.getDefaultMessageStore().getMessageStoreConfig()                            .getHaHousekeepingInterval()) {                            log.warn("HAClient, housekeeping, found this connection[" + this.masterAddress                                + "] expired, " + interval);                            this.closeMaster();                            log.warn("HAClient, master not response some time, so close connection");                        }                    } else {                        this.waitForRunning(1000 * 5);                    }                } catch (Exception e) {                    log.warn(this.getServiceName() + " service has exception. ", e);                    this.waitForRunning(1000 * 5);                }            }
            log.info(this.getServiceName() + " service end");        }

进入方法,连接master,org.apache.rocketmq.store.ha.HAService.HAClient#connectMaster

 private boolean connectMaster() throws ClosedChannelException {            if (null == socketChannel) {                String addr = this.masterAddress.get();                if (addr != null) {
                    SocketAddress socketAddress = RemotingUtil.string2SocketAddress(addr);                    if (socketAddress != null) {                        this.socketChannel = RemotingUtil.connect(socketAddress);                        if (this.socketChannel != null) {                            this.socketChannel.register(this.selector, SelectionKey.OP_READ);                        }                    }                }
                this.currentReportedOffset = HAService.this.defaultMessageStore.getMaxPhyOffset();
                this.lastWriteTimestamp = System.currentTimeMillis();            }
            return this.socketChannel != null;        }

返回方法,关闭master,org.apache.rocketmq.store.ha.HAService.HAClient#closeMaster

 private void closeMaster() {            if (null != this.socketChannel) {                try {
                    SelectionKey sk = this.socketChannel.keyFor(this.selector);                    if (sk != null) {                        sk.cancel();                    }
                    this.socketChannel.close();
                    this.socketChannel = null;                } catch (IOException e) {                    log.warn("closeMaster exception. ", e);                }
                this.lastWriteTimestamp = 0;                this.dispatchPostion = 0;
                this.byteBufferBackup.position(0);                this.byteBufferBackup.limit(READ_MAX_BUFFER_SIZE);
                this.byteBufferRead.position(0);                this.byteBufferRead.limit(READ_MAX_BUFFER_SIZE);            }        }

进入方法,处理读事件,org.apache.rocketmq.store.ha.HAService.HAClient#processReadEvent

  private boolean processReadEvent() {            int readSizeZeroTimes = 0;            while (this.byteBufferRead.hasRemaining()) {                try {                    int readSize = this.socketChannel.read(this.byteBufferRead);                    if (readSize > 0) {                        lastWriteTimestamp = HAService.this.defaultMessageStore.getSystemClock().now();                        readSizeZeroTimes = 0;                        boolean result = this.dispatchReadRequest();                        if (!result) {                            log.error("HAClient, dispatchReadRequest error");                            return false;                        }                    } else if (readSize == 0) {                        if (++readSizeZeroTimes >= 3) {                            break;                        }                    } else {                        log.info("HAClient, processReadEvent read socket < 0");                        return false;                    }                } catch (IOException e) {                    log.info("HAClient, processReadEvent read socket exception", e);                    return false;                }            }
            return true;        }

返回方法,添加调度服务,org.apache.rocketmq.store.DefaultMessageStore#addScheduleTask

 private void addScheduleTask() {
        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {//              定期清除文件=》                DefaultMessageStore.this.cleanFilesPeriodically();            }        }, 1000 * 60, this.messageStoreConfig.getCleanResourceInterval(), TimeUnit.MILLISECONDS);
        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                DefaultMessageStore.this.checkSelf();            }        }, 1, 10, TimeUnit.MINUTES);
        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                if (DefaultMessageStore.this.getMessageStoreConfig().isDebugLockEnable()) {                    try {                        if (DefaultMessageStore.this.commitLog.getBeginTimeInLock() != 0) {                            long lockTime = System.currentTimeMillis() - DefaultMessageStore.this.commitLog.getBeginTimeInLock();                            if (lockTime > 1000 && lockTime < 10000000) {
                                String stack = UtilAll.jstack();                                final String fileName = System.getProperty("user.home") + File.separator + "debug/lock/stack-"                                    + DefaultMessageStore.this.commitLog.getBeginTimeInLock() + "-" + lockTime;                                MixAll.string2FileNotSafe(stack, fileName);                            }                        }                    } catch (Exception e) {                    }                }            }        }, 1, 1, TimeUnit.SECONDS);
        // this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {        // @Override        // public void run() {        // DefaultMessageStore.this.cleanExpiredConsumerQueue();        // }        // }, 1, 1, TimeUnit.HOURS);    }

进入方法,定期清除文件,org.apache.rocketmq.store.DefaultMessageStore#cleanFilesPeriodically

 private void cleanFilesPeriodically() {//        =》        this.cleanCommitLogService.run();//        =》        this.cleanConsumeQueueService.run();    }

进入方法,org.apache.rocketmq.store.DefaultMessageStore.CleanCommitLogService#run

     public void run() {            try {//                删除过期文件=》                this.deleteExpiredFiles();
//                重新删除该删除的文件=》                this.redeleteHangedFile();            } catch (Throwable e) {                DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e);            }        }

进入方法,删除过期文件,org.apache.rocketmq.store.DefaultMessageStore.CleanCommitLogService#deleteExpiredFiles

       private void deleteExpiredFiles() {            int deleteCount = 0;            long fileReservedTime = DefaultMessageStore.this.getMessageStoreConfig().getFileReservedTime();            int deletePhysicFilesInterval = DefaultMessageStore.this.getMessageStoreConfig().getDeleteCommitLogFilesInterval();            int destroyMapedFileIntervalForcibly = DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly();
//            时间到了该删除            boolean timeup = this.isTimeToDelete();//            磁盘达到百分比改删除            boolean spacefull = this.isSpaceToDelete();            boolean manualDelete = this.manualDeleteFileSeveralTimes > 0;
            if (timeup || spacefull || manualDelete) {
                if (manualDelete)                    this.manualDeleteFileSeveralTimes--;
                boolean cleanAtOnce = DefaultMessageStore.this.getMessageStoreConfig().isCleanFileForciblyEnable() && this.cleanImmediately;
                log.info("begin to delete before {} hours file. timeup: {} spacefull: {} manualDeleteFileSeveralTimes: {} cleanAtOnce: {}",                    fileReservedTime,                    timeup,                    spacefull,                    manualDeleteFileSeveralTimes,                    cleanAtOnce);
                fileReservedTime *= 60 * 60 * 1000;
//                =》                deleteCount = DefaultMessageStore.this.commitLog.deleteExpiredFile(fileReservedTime, deletePhysicFilesInterval,                    destroyMapedFileIntervalForcibly, cleanAtOnce);                if (deleteCount > 0) {                } else if (spacefull) {                    log.warn("disk space will be full soon, but delete file failed.");                }            }        }

进入方法,org.apache.rocketmq.store.CommitLog#deleteExpiredFile

  public int deleteExpiredFile(        final long expiredTime,        final int deleteFilesInterval,        final long intervalForcibly,        final boolean cleanImmediately    ) {//        按时间删除过期文件=》        return this.mappedFileQueue.deleteExpiredFileByTime(expiredTime, deleteFilesInterval, intervalForcibly, cleanImmediately);    }

进入方法,按时间删除过期文件,org.apache.rocketmq.store.MappedFileQueue#deleteExpiredFileByTime

  public int deleteExpiredFileByTime(final long expiredTime,        final int deleteFilesInterval,        final long intervalForcibly,        final boolean cleanImmediately) {        Object[] mfs = this.copyMappedFiles(0);
        if (null == mfs)            return 0;
        int mfsLength = mfs.length - 1;        int deleteCount = 0;        List<MappedFile> files = new ArrayList<MappedFile>();        if (null != mfs) {            for (int i = 0; i < mfsLength; i++) {                MappedFile mappedFile = (MappedFile) mfs[i];//                文件最大存储时间                long liveMaxTimestamp = mappedFile.getLastModifiedTimestamp() + expiredTime;                if (System.currentTimeMillis() >= liveMaxTimestamp || cleanImmediately) {//                    文件销毁=》                    if (mappedFile.destroy(intervalForcibly)) {                        files.add(mappedFile);                        deleteCount++;
                        if (files.size() >= DELETE_FILES_BATCH_MAX) {                            break;                        }
                        if (deleteFilesInterval > 0 && (i + 1) < mfsLength) {                            try {                                Thread.sleep(deleteFilesInterval);                            } catch (InterruptedException e) {                            }                        }                    } else {                        break;                    }                } else {                    //avoid deleting files in the middle                    break;                }            }        }
//        删除映射文件队列中映射文件=》        deleteExpiredFile(files);
        return deleteCount;    }

进入方法,删除映射文件队列中映射文件,org.apache.rocketmq.store.MappedFileQueue#deleteExpiredFile

  void deleteExpiredFile(List<MappedFile> files) {
        if (!files.isEmpty()) {
            Iterator<MappedFile> iterator = files.iterator();            while (iterator.hasNext()) {                MappedFile cur = iterator.next();                if (!this.mappedFiles.contains(cur)) {                    iterator.remove();                    log.info("This mappedFile {} is not contained by mappedFiles, so skip it.", cur.getFileName());                }            }
            try {                if (!this.mappedFiles.removeAll(files)) {                    log.error("deleteExpiredFile remove failed.");                }            } catch (Exception e) {                log.error("deleteExpiredFile has exception.", e);            }        }    }

返回方法,重新删除该删除的文件,org.apache.rocketmq.store.DefaultMessageStore.CleanCommitLogService#redeleteHangedFile

   private void redeleteHangedFile() {            int interval = DefaultMessageStore.this.getMessageStoreConfig().getRedeleteHangedFileInterval();            long currentTimestamp = System.currentTimeMillis();            if ((currentTimestamp - this.lastRedeleteTimestamp) > interval) {                this.lastRedeleteTimestamp = currentTimestamp;                int destroyMapedFileIntervalForcibly =                    DefaultMessageStore.this.getMessageStoreConfig().getDestroyMapedFileIntervalForcibly();//                =》                if (DefaultMessageStore.this.commitLog.retryDeleteFirstFile(destroyMapedFileIntervalForcibly)) {                }            }        }

进入方法,org.apache.rocketmq.store.MappedFileQueue#retryDeleteFirstFile

 public boolean retryDeleteFirstFile(final long intervalForcibly) {//        获取映射文件队列中第一个文件=》        MappedFile mappedFile = this.getFirstMappedFile();        if (mappedFile != null) {            if (!mappedFile.isAvailable()) {                log.warn("the mappedFile was destroyed once, but still alive, " + mappedFile.getFileName());//                文件销毁=》                boolean result = mappedFile.destroy(intervalForcibly);                if (result) {                    log.info("the mappedFile re delete OK, " + mappedFile.getFileName());                    List<MappedFile> tmpFiles = new ArrayList<MappedFile>();                    tmpFiles.add(mappedFile);//                    删除映射文件队列中文件=》                    this.deleteExpiredFile(tmpFiles);                } else {                    log.warn("the mappedFile re delete failed, " + mappedFile.getFileName());                }
                return result;            }        }
        return false;    }

返回方法,org.apache.rocketmq.store.DefaultMessageStore.CleanConsumeQueueService#run

 public void run() {            try {//                删除过期文件=》                this.deleteExpiredFiles();            } catch (Throwable e) {                DefaultMessageStore.log.warn(this.getServiceName() + " service has exception. ", e);            }        }

进入方法,删除过期文件,org.apache.rocketmq.store.DefaultMessageStore.CleanConsumeQueueService#deleteExpiredFiles

    private void deleteExpiredFiles() {            int deleteLogicsFilesInterval = DefaultMessageStore.this.getMessageStoreConfig().getDeleteConsumeQueueFilesInterval();
            long minOffset = DefaultMessageStore.this.commitLog.getMinOffset();            if (minOffset > this.lastPhysicalMinOffset) {                this.lastPhysicalMinOffset = minOffset;
                ConcurrentMap<String, ConcurrentMap<Integer, ConsumeQueue>> tables = DefaultMessageStore.this.consumeQueueTable;
                for (ConcurrentMap<Integer, ConsumeQueue> maps : tables.values()) {                    for (ConsumeQueue logic : maps.values()) {//                        =》                        int deleteCount = logic.deleteExpiredFile(minOffset);
                        if (deleteCount > 0 && deleteLogicsFilesInterval > 0) {                            try {                                Thread.sleep(deleteLogicsFilesInterval);                            } catch (InterruptedException ignored) {                            }                        }                    }                }
//                删除索引文件=》                DefaultMessageStore.this.indexService.deleteExpiredFile(minOffset);            }        }

进入方法,org.apache.rocketmq.store.ConsumeQueue#deleteExpiredFile

  public int deleteExpiredFile(long offset) {//        按offset删除过期文件=》        int cnt = this.mappedFileQueue.deleteExpiredFileByOffset(offset, CQ_STORE_UNIT_SIZE);//        修改最小的offset=》        this.correctMinOffset(offset);        return cnt;    }

进入方法,按offset删除过期文件,org.apache.rocketmq.store.MappedFileQueue#deleteExpiredFileByOffset介绍过了。

返回方法,修改最小的offset,org.apache.rocketmq.store.ConsumeQueue#correctMinOffset介绍过了。

进入方法,删除索引文件,org.apache.rocketmq.store.index.IndexService#deleteExpiredFile(long)

  public void deleteExpiredFile(long offset) {        Object[] files = null;        try {            this.readWriteLock.readLock().lock();            if (this.indexFileList.isEmpty()) {                return;            }
            long endPhyOffset = this.indexFileList.get(0).getEndPhyOffset();            if (endPhyOffset < offset) {                files = this.indexFileList.toArray();            }        } catch (Exception e) {            log.error("destroy exception", e);        } finally {            this.readWriteLock.readLock().unlock();        }
        if (files != null) {            List<IndexFile> fileList = new ArrayList<IndexFile>();            for (int i = 0; i < (files.length - 1); i++) {                IndexFile f = (IndexFile) files[i];                if (f.getEndPhyOffset() < offset) {                    fileList.add(f);                } else {                    break;                }            }
//            删除过期的索引文件=》            this.deleteExpiredFile(fileList);        }    }

进入方法,删除过期的索引文件,org.apache.rocketmq.store.index.IndexService#deleteExpiredFile(java.util.List<org.apache.rocketmq.store.index.IndexFile>)

  private void deleteExpiredFile(List<IndexFile> files) {        if (!files.isEmpty()) {            try {                this.readWriteLock.writeLock().lock();                for (IndexFile file : files) {                    boolean destroyed = file.destroy(3000);                    destroyed = destroyed && this.indexFileList.remove(file);                    if (!destroyed) {                        log.error("deleteExpiredFile remove failed.");                        break;                    }                }            } catch (Exception e) {                log.error("deleteExpiredFile has exception.", e);            } finally {                this.readWriteLock.writeLock().unlock();            }        }    }

返回方法,注册broker,org.apache.rocketmq.broker.BrokerController#registerBrokerAll介绍过了。

进入方法,broker快速失败服务,org.apache.rocketmq.broker.latency.BrokerFastFailure#start

 public void start() {        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                if (brokerController.getBrokerConfig().isBrokerFastFailureEnable()) {//                    清除过期的请求=》                    cleanExpiredRequest();                }            }        }, 1000, 10, TimeUnit.MILLISECONDS);    }

进入方法,清除过期的请求,org.apache.rocketmq.broker.latency.BrokerFastFailure#cleanExpiredRequest

 private void cleanExpiredRequest() {//        系统繁忙        while (this.brokerController.getMessageStore().isOSPageCacheBusy()) {            try {                if (!this.brokerController.getSendThreadPoolQueue().isEmpty()) {                    final Runnable runnable = this.brokerController.getSendThreadPoolQueue().poll(0, TimeUnit.SECONDS);                    if (null == runnable) {                        break;                    }
                    final RequestTask rt = castRunnable(runnable);                    rt.returnResponse(RemotingSysResponseCode.SYSTEM_BUSY, String.format("[PCBUSY_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: %sms, size of queue: %d", System.currentTimeMillis() - rt.getCreateTimestamp(), this.brokerController.getSendThreadPoolQueue().size()));                } else {                    break;                }            } catch (Throwable ignored) {            }        }
        cleanExpiredRequestInQueue(this.brokerController.getSendThreadPoolQueue(),            this.brokerController.getBrokerConfig().getWaitTimeMillsInSendQueue());
        cleanExpiredRequestInQueue(this.brokerController.getPullThreadPoolQueue(),            this.brokerController.getBrokerConfig().getWaitTimeMillsInPullQueue());
        cleanExpiredRequestInQueue(this.brokerController.getHeartbeatThreadPoolQueue(),            this.brokerController.getBrokerConfig().getWaitTimeMillsInHeartbeatQueue());    }

返回方法,分布式消息事务服务启动,org.apache.rocketmq.broker.transaction.TransactionalMessageCheckService#start

  @Override    public void start() {//        这里也是自旋锁的应用        if (started.compareAndSet(false, true)) {            super.start();            this.brokerController.getTransactionalMessageService().open();        }    }

返回方法,org.apache.rocketmq.broker.BrokerStartup#start结束。

 

说在最后

本次解析仅代表个人观点,仅供参考

 

加入技术微信群

钉钉技术群

转载于:https://my.oschina.net/u/3775437/blog/3097035

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值