All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aliyun.openservices.loghub.client.LogHubHeartBeat Maven / Gradle / Ivy

There is a newer version: 0.6.7
Show newest version
package com.aliyun.openservices.loghub.client;

import com.aliyun.openservices.loghub.client.config.LogHubConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LogHubHeartBeat {
    private static final Logger LOG = LoggerFactory.getLogger(LogHubHeartBeat.class);
    private static final long STOP_TIMEOUT_SECS = 10L;

    private ScheduledExecutorService executorService;
    private final LogHubClientAdapter client;
    private final long intervalMills;
    private final int timeoutSecs;
    private Set heldShards;
    private Set heartShards;
    private long lastSuccessTime;

    public LogHubHeartBeat(LogHubClientAdapter client,
                           LogHubConfig config) {
        this.client = client;
        this.intervalMills = config.getHeartBeatIntervalMillis();
        this.timeoutSecs = config.getTimeoutInSeconds();
        heldShards = new HashSet();
        heartShards = new HashSet();
    }

    public void start() {
        executorService = Executors.newScheduledThreadPool(1, new LogThreadFactory());
        executorService.scheduleWithFixedDelay(new HeartBeatRunnable(), 0L,
                intervalMills, TimeUnit.MILLISECONDS);
        LOG.info("Background heartbeat thread started, interval {}", intervalMills);
    }

    /**
     * Stops background threads.
     */
    public void stop() {
        LoghubClientUtil.shutdownThreadPool(executorService, STOP_TIMEOUT_SECS);
    }

    public synchronized List getHeldShards() {
        return new ArrayList<>(heldShards);
    }

    public synchronized void removeFromHeartShards(int shard) {
        heartShards.remove(shard);
        LOG.warn("Cancel heart beating for shard={}", shard);
    }

    private synchronized void heartBeat() {
        long nowMillis = System.currentTimeMillis();
        try {
            LOG.debug("Sending heartbeat {}", Arrays.toString(heartShards.toArray()));
            List shards = client.HeartBeat(new ArrayList(heartShards));
            LOG.info("Heartbeat response: {}", shards);
            heldShards = new HashSet(shards);
            heartShards.addAll(shards);
            lastSuccessTime = nowMillis;
        } catch (Exception ex) {
            LOG.error("Error sending heartbeat, project {}, logstore {}, consumer {}",
                    client.getProject(),
                    client.getLogstore(),
                    client.getConsumer(),
                    ex);
            if (nowMillis - lastSuccessTime > (timeoutSecs * 1000L) + intervalMills) {
                // The current consumer should already been removed from consumer group
                heldShards.clear();
                heartShards.clear();
                LOG.warn("Heartbeat failed since {}, clear held shards", lastSuccessTime);
            }
        }
    }

    public synchronized void markIdle(int shard) {
        heldShards.remove(shard);
    }

    private class HeartBeatRunnable implements Runnable {

        @Override
        public void run() {
            heartBeat();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy