Search in sources :

Example 6 with KeepAliveRequest

use of io.atomix.protocols.raft.protocol.KeepAliveRequest in project atomix by atomix.

the class RaftSessionManager method keepAliveSessions.

/**
 * Sends a keep-alive request to the cluster.
 */
private synchronized void keepAliveSessions(long lastKeepAliveTime, long sessionTimeout) {
    // Filter the list of sessions by timeout.
    List<RaftSessionState> needKeepAlive = sessions.values().stream().filter(session -> session.getSessionTimeout() == sessionTimeout).collect(Collectors.toList());
    // If no sessions need keep-alives to be sent, skip and reschedule the keep-alive.
    if (needKeepAlive.isEmpty()) {
        return;
    }
    // Allocate session IDs, command response sequence numbers, and event index arrays.
    long[] sessionIds = new long[needKeepAlive.size()];
    long[] commandResponses = new long[needKeepAlive.size()];
    long[] eventIndexes = new long[needKeepAlive.size()];
    // For each session that needs to be kept alive, populate batch request arrays.
    int i = 0;
    for (RaftSessionState sessionState : needKeepAlive) {
        sessionIds[i] = sessionState.getSessionId().id();
        commandResponses[i] = sessionState.getCommandResponse();
        eventIndexes[i] = sessionState.getEventIndex();
        i++;
    }
    log.trace("Keeping {} sessions alive", sessionIds.length);
    KeepAliveRequest request = KeepAliveRequest.builder().withSessionIds(sessionIds).withCommandSequences(commandResponses).withEventIndexes(eventIndexes).build();
    long keepAliveTime = System.currentTimeMillis();
    connection.keepAlive(request).whenComplete((response, error) -> {
        if (open.get()) {
            long delta = System.currentTimeMillis() - keepAliveTime;
            if (error == null) {
                // If the request was successful, update the address selector and schedule the next keep-alive.
                if (response.status() == RaftResponse.Status.OK) {
                    selectorManager.resetAll(response.leader(), response.members());
                    // Iterate through sessions and close sessions that weren't kept alive by the request (have already been closed).
                    Set<Long> keptAliveSessions = Sets.newHashSet(Longs.asList(response.sessionIds()));
                    for (RaftSessionState session : needKeepAlive) {
                        if (keptAliveSessions.contains(session.getSessionId().id())) {
                            session.setState(PrimitiveState.CONNECTED);
                        } else {
                            session.setState(PrimitiveState.EXPIRED);
                        }
                    }
                    scheduleKeepAlive(System.currentTimeMillis(), sessionTimeout, delta);
                } else // We will continue to retry until the session expiration has passed.
                if (System.currentTimeMillis() - lastKeepAliveTime < sessionTimeout) {
                    selectorManager.resetAll(null, connection.members());
                    keepAliveSessions(lastKeepAliveTime, sessionTimeout);
                } else // If no leader was set, set the session state to unstable and schedule another keep-alive.
                {
                    needKeepAlive.forEach(s -> s.setState(PrimitiveState.SUSPENDED));
                    selectorManager.resetAll();
                    scheduleKeepAlive(lastKeepAliveTime, sessionTimeout, delta);
                }
            } else // again with no delay.
            if (System.currentTimeMillis() - lastKeepAliveTime < sessionTimeout && connection.leader() != null) {
                selectorManager.resetAll(null, connection.members());
                keepAliveSessions(lastKeepAliveTime, sessionTimeout);
            } else // If no leader was set, set the session state to unstable and schedule another keep-alive.
            {
                needKeepAlive.forEach(s -> s.setState(PrimitiveState.SUSPENDED));
                selectorManager.resetAll();
                scheduleKeepAlive(lastKeepAliveTime, sessionTimeout, delta);
            }
        }
    });
}
Also used : RaftClient(io.atomix.protocols.raft.RaftClient) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) CloseSessionRequest(io.atomix.protocols.raft.protocol.CloseSessionRequest) ContextualLoggerFactory(io.atomix.utils.logging.ContextualLoggerFactory) RaftClientProtocol(io.atomix.protocols.raft.protocol.RaftClientProtocol) SessionId(io.atomix.primitive.session.SessionId) Lists(com.google.common.collect.Lists) RaftResponse(io.atomix.protocols.raft.protocol.RaftResponse) Duration(java.time.Duration) Map(java.util.Map) MemberId(io.atomix.cluster.MemberId) Scheduled(io.atomix.utils.concurrent.Scheduled) Futures(io.atomix.utils.concurrent.Futures) Longs(com.google.common.primitives.Longs) HeartbeatRequest(io.atomix.protocols.raft.protocol.HeartbeatRequest) Logger(org.slf4j.Logger) PrimitiveState(io.atomix.primitive.PrimitiveState) LoggerContext(io.atomix.utils.logging.LoggerContext) HeartbeatResponse(io.atomix.protocols.raft.protocol.HeartbeatResponse) Collection(java.util.Collection) CommunicationStrategy(io.atomix.protocols.raft.session.CommunicationStrategy) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Set(java.util.Set) ReadConsistency(io.atomix.protocols.raft.ReadConsistency) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) ThreadContext(io.atomix.utils.concurrent.ThreadContext) OpenSessionRequest(io.atomix.protocols.raft.protocol.OpenSessionRequest) ThreadContextFactory(io.atomix.utils.concurrent.ThreadContextFactory) Objects(java.util.Objects) List(java.util.List) KeepAliveRequest(io.atomix.protocols.raft.protocol.KeepAliveRequest) ServiceConfig(io.atomix.primitive.service.ServiceConfig) PrimitiveType(io.atomix.primitive.PrimitiveType) RaftException(io.atomix.protocols.raft.RaftException) Serializer(io.atomix.utils.serializer.Serializer) MoreObjects.toStringHelper(com.google.common.base.MoreObjects.toStringHelper) KeepAliveRequest(io.atomix.protocols.raft.protocol.KeepAliveRequest)

Aggregations

KeepAliveRequest (io.atomix.protocols.raft.protocol.KeepAliveRequest)6 CompletableFuture (java.util.concurrent.CompletableFuture)4 MoreObjects.toStringHelper (com.google.common.base.MoreObjects.toStringHelper)2 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)2 Lists (com.google.common.collect.Lists)2 Sets (com.google.common.collect.Sets)2 Longs (com.google.common.primitives.Longs)2 PrimitiveType (io.atomix.primitive.PrimitiveType)2 SessionId (io.atomix.primitive.session.SessionId)2 RaftClient (io.atomix.protocols.raft.RaftClient)2 RaftException (io.atomix.protocols.raft.RaftException)2 ReadConsistency (io.atomix.protocols.raft.ReadConsistency)2 CloseSessionRequest (io.atomix.protocols.raft.protocol.CloseSessionRequest)2 HeartbeatRequest (io.atomix.protocols.raft.protocol.HeartbeatRequest)2 HeartbeatResponse (io.atomix.protocols.raft.protocol.HeartbeatResponse)2 OpenSessionRequest (io.atomix.protocols.raft.protocol.OpenSessionRequest)2 RaftClientProtocol (io.atomix.protocols.raft.protocol.RaftClientProtocol)2 RaftResponse (io.atomix.protocols.raft.protocol.RaftResponse)2 Futures (io.atomix.utils.concurrent.Futures)2 Scheduled (io.atomix.utils.concurrent.Scheduled)2