@SneakyThrows
    private void evictClusterNode(HeartbeatMsg heartbeat) {
        log.debug("evict cluster node");
        ComponentHeartbeat componentHeartbeat = heartbeat.componentHeartbeat();
        ClusterInfo clusterInfo = clusterInfoCache.getIfPresent(componentHeartbeat);
        if (clusterInfo == null) {
            log.error("not found any cluster by name={} and type={}", componentHeartbeat.getClusterName(),
                    componentHeartbeat.getComponentType());
            return;
        }

        // protocolType may be null, and the protocolTypes' length may be less than ports' length
        String[] ips = heartbeat.getIp().split(InlongConstants.COMMA);
        String port = heartbeat.getPort();
        String[] ports = null;
        if (StringUtils.isNotBlank(port)) {
            ports = port.split(InlongConstants.COMMA);
            if (ports.length < ips.length) {
                ports = null;
            }
        }
        String protocolType = heartbeat.getProtocolType();
        String[] protocolTypes = null;
        if (StringUtils.isNotBlank(protocolType) && ips.length > 1) {
            protocolTypes = protocolType.split(InlongConstants.COMMA);
            if (protocolTypes.length < ips.length) {
                protocolTypes = null;
            }
        }
        // If the manager has multiple nodes, need to determine that the heartbeat is updated
        // heartbeatInterval() is the reporting interval of cluster nodes, multiplied by two to prevent network
        // fluctuations
        ComponentHeartbeatEntity componentHeartbeatEntity = componentHeartbeatMapper.selectTimeOutHeartBeat(
                componentHeartbeat.getComponentType(), componentHeartbeat.getIp(), heartbeatInterval() * 6L);
        if (componentHeartbeatEntity != null) {
            heartbeatCache.put(componentHeartbeat, heartbeat);
            return;
        }

        for (int i = 0; i < ips.length; i++) {
            // deep clone the heartbeat
            HeartbeatMsg heartbeatMsg = JsonUtils.parseObject(JsonUtils.toJsonByte(heartbeat), HeartbeatMsg.class);
            assert heartbeatMsg != null;
            if (StringUtils.isNotBlank(port) && ports != null) {
                heartbeatMsg.setPort(ports[i].trim());
            }
            heartbeatMsg.setIp(ips[i].trim());
            if (protocolTypes != null) {
                heartbeatMsg.setProtocolType(protocolTypes[i]);
            } else {
                heartbeatMsg.setProtocolType(protocolType);
            }
            if (Objects.equals(heartbeat.getComponentType(), ComponentTypeEnum.Agent.getType())) {
                heartbeatMsg.setProtocolType(null);
                heartbeatMsg.setPort(null);
            }
            InlongClusterNodeEntity clusterNode = getClusterNode(clusterInfo, heartbeatMsg);
            if (clusterNode == null) {
                log.error("not found any cluster node by type={}, ip={}, port={}",
                        heartbeat.getComponentType(), heartbeat.getIp(), heartbeat.getPort());
                return;
            }
            clusterNode.setStatus(NodeStatus.HEARTBEAT_TIMEOUT.getStatus());
            clusterNodeMapper.updateById(clusterNode);
        }
    }
Check whether the configuration information carried in the heartbeat has been updated

@param oldHB last heartbeat msg
@param newHB current heartbeat msg
@return
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/heartbeat/HeartbeatManager.java