org.apache.flink.runtime.jobmaster.JobMaster Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.flink.runtime.jobmaster;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.common.JobID;
import org.apache.flink.api.common.JobStatus;
import org.apache.flink.api.common.functions.AggregateFunction;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.configuration.JobManagerOptions;
import org.apache.flink.core.execution.CheckpointType;
import org.apache.flink.core.execution.SavepointFormatType;
import org.apache.flink.core.failure.FailureEnricher;
import org.apache.flink.queryablestate.KvStateID;
import org.apache.flink.runtime.accumulators.AccumulatorSnapshot;
import org.apache.flink.runtime.blob.BlobWriter;
import org.apache.flink.runtime.blocklist.BlockedNode;
import org.apache.flink.runtime.blocklist.BlocklistContext;
import org.apache.flink.runtime.blocklist.BlocklistHandler;
import org.apache.flink.runtime.blocklist.BlocklistUtils;
import org.apache.flink.runtime.checkpoint.CheckpointMetrics;
import org.apache.flink.runtime.checkpoint.CheckpointStatsSnapshot;
import org.apache.flink.runtime.checkpoint.CompletedCheckpoint;
import org.apache.flink.runtime.checkpoint.SubTaskInitializationMetrics;
import org.apache.flink.runtime.checkpoint.TaskStateSnapshot;
import org.apache.flink.runtime.clusterframework.types.AllocationID;
import org.apache.flink.runtime.clusterframework.types.ResourceID;
import org.apache.flink.runtime.execution.ExecutionState;
import org.apache.flink.runtime.executiongraph.ExecutionAttemptID;
import org.apache.flink.runtime.executiongraph.JobStatusListener;
import org.apache.flink.runtime.heartbeat.HeartbeatListener;
import org.apache.flink.runtime.heartbeat.HeartbeatManager;
import org.apache.flink.runtime.heartbeat.HeartbeatReceiver;
import org.apache.flink.runtime.heartbeat.HeartbeatSender;
import org.apache.flink.runtime.heartbeat.HeartbeatServices;
import org.apache.flink.runtime.heartbeat.NoOpHeartbeatManager;
import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
import org.apache.flink.runtime.io.network.partition.JobMasterPartitionTracker;
import org.apache.flink.runtime.io.network.partition.PartitionTrackerFactory;
import org.apache.flink.runtime.io.network.partition.ResultPartitionID;
import org.apache.flink.runtime.jobgraph.IntermediateDataSetID;
import org.apache.flink.runtime.jobgraph.JobGraph;
import org.apache.flink.runtime.jobgraph.JobResourceRequirements;
import org.apache.flink.runtime.jobgraph.JobVertexID;
import org.apache.flink.runtime.jobgraph.OperatorID;
import org.apache.flink.runtime.jobmanager.OnCompletionActions;
import org.apache.flink.runtime.jobmanager.PartitionProducerDisposedException;
import org.apache.flink.runtime.jobmaster.factories.JobManagerJobMetricGroupFactory;
import org.apache.flink.runtime.jobmaster.slotpool.BlocklistDeclarativeSlotPoolFactory;
import org.apache.flink.runtime.jobmaster.slotpool.DeclarativeSlotPoolFactory;
import org.apache.flink.runtime.jobmaster.slotpool.DefaultDeclarativeSlotPoolFactory;
import org.apache.flink.runtime.jobmaster.slotpool.SlotPoolService;
import org.apache.flink.runtime.leaderretrieval.LeaderRetrievalListener;
import org.apache.flink.runtime.leaderretrieval.LeaderRetrievalService;
import org.apache.flink.runtime.messages.Acknowledge;
import org.apache.flink.runtime.messages.FlinkJobNotFoundException;
import org.apache.flink.runtime.messages.checkpoint.DeclineCheckpoint;
import org.apache.flink.runtime.metrics.groups.JobManagerJobMetricGroup;
import org.apache.flink.runtime.operators.coordination.CoordinationRequest;
import org.apache.flink.runtime.operators.coordination.CoordinationResponse;
import org.apache.flink.runtime.operators.coordination.OperatorEvent;
import org.apache.flink.runtime.query.KvStateLocation;
import org.apache.flink.runtime.query.UnknownKvStateLocation;
import org.apache.flink.runtime.registration.RegisteredRpcConnection;
import org.apache.flink.runtime.registration.RegistrationResponse;
import org.apache.flink.runtime.registration.RetryingRegistration;
import org.apache.flink.runtime.resourcemanager.ResourceManagerGateway;
import org.apache.flink.runtime.resourcemanager.ResourceManagerId;
import org.apache.flink.runtime.rpc.FatalErrorHandler;
import org.apache.flink.runtime.rpc.FencedRpcEndpoint;
import org.apache.flink.runtime.rpc.RpcService;
import org.apache.flink.runtime.rpc.RpcServiceUtils;
import org.apache.flink.runtime.scheduler.ExecutionGraphInfo;
import org.apache.flink.runtime.scheduler.SchedulerNG;
import org.apache.flink.runtime.shuffle.JobShuffleContext;
import org.apache.flink.runtime.shuffle.JobShuffleContextImpl;
import org.apache.flink.runtime.shuffle.PartitionWithMetrics;
import org.apache.flink.runtime.shuffle.ShuffleDescriptor;
import org.apache.flink.runtime.shuffle.ShuffleMaster;
import org.apache.flink.runtime.slots.ResourceRequirement;
import org.apache.flink.runtime.state.KeyGroupRange;
import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
import org.apache.flink.runtime.taskexecutor.TaskExecutorToJobManagerHeartbeatPayload;
import org.apache.flink.runtime.taskexecutor.slot.SlotOffer;
import org.apache.flink.runtime.taskmanager.TaskExecutionState;
import org.apache.flink.runtime.taskmanager.TaskManagerLocation;
import org.apache.flink.runtime.taskmanager.TaskManagerLocation.ResolutionMode;
import org.apache.flink.runtime.taskmanager.UnresolvedTaskManagerLocation;
import org.apache.flink.util.ExceptionUtils;
import org.apache.flink.util.FlinkException;
import org.apache.flink.util.FlinkRuntimeException;
import org.apache.flink.util.InstantiationUtil;
import org.apache.flink.util.MdcUtils;
import org.apache.flink.util.SerializedValue;
import org.apache.flink.util.concurrent.FutureUtils;
import org.slf4j.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import static org.apache.flink.runtime.checkpoint.TaskStateSnapshot.deserializeTaskStateSnapshot;
import static org.apache.flink.util.Preconditions.checkNotNull;
import static org.apache.flink.util.Preconditions.checkState;
/**
* JobMaster implementation. The job master is responsible for the execution of a single {@link
* JobGraph}.
*
* It offers the following methods as part of its rpc interface to interact with the JobMaster
* remotely:
*
*
* - {@link #updateTaskExecutionState} updates the task execution state for given task
*
*/
public class JobMaster extends FencedRpcEndpoint
implements JobMasterGateway, JobMasterService {
/** Default names for Flink's distributed components. */
public static final String JOB_MANAGER_NAME = "jobmanager";
// ------------------------------------------------------------------------
private final JobMasterConfiguration jobMasterConfiguration;
private final ResourceID resourceId;
private final JobGraph jobGraph;
private final Duration rpcTimeout;
private final HighAvailabilityServices highAvailabilityServices;
private final BlobWriter blobWriter;
private final HeartbeatServices heartbeatServices;
private final ScheduledExecutorService futureExecutor;
private final Executor ioExecutor;
private final OnCompletionActions jobCompletionActions;
private final FatalErrorHandler fatalErrorHandler;
private final ClassLoader userCodeLoader;
private final SlotPoolService slotPoolService;
private final long initializationTimestamp;
private final boolean retrieveTaskManagerHostName;
// --------- ResourceManager --------
private final LeaderRetrievalService resourceManagerLeaderRetriever;
// --------- TaskManagers --------
private final Map registeredTaskManagers;
private final ShuffleMaster> shuffleMaster;
// --------- Scheduler --------
private final SchedulerNG schedulerNG;
private final JobManagerJobStatusListener jobStatusListener;
private final JobManagerJobMetricGroup jobManagerJobMetricGroup;
// -------- Misc ---------
private final Map accumulators;
private final JobMasterPartitionTracker partitionTracker;
private final ExecutionDeploymentTracker executionDeploymentTracker;
private final ExecutionDeploymentReconciler executionDeploymentReconciler;
private final Collection failureEnrichers;
// -------- Mutable fields ---------
@Nullable private ResourceManagerAddress resourceManagerAddress;
@Nullable private ResourceManagerConnection resourceManagerConnection;
@Nullable private EstablishedResourceManagerConnection establishedResourceManagerConnection;
private HeartbeatManager
taskManagerHeartbeatManager;
private HeartbeatManager resourceManagerHeartbeatManager;
private final BlocklistHandler blocklistHandler;
private final Map fetchedPartitionsWithMetrics =
new HashMap<>();
/**
* A flag that indicates whether to fetch and retain partitions on task managers. This will
* apply to future TaskManager registrations as well as already registered TaskManagers. The
* flag will be set to true when starting batch job recovery and set to false after all required
* partitions, as defined in {@code requireToFetchPartitions}, are either fetched or when a
* timeout occurs.
*/
private boolean fetchAndRetainPartitions = false;
private Set partitionsToFetch;
private CompletableFuture> fetchPartitionsFuture;
// ------------------------------------------------------------------------
public JobMaster(
RpcService rpcService,
JobMasterId jobMasterId,
JobMasterConfiguration jobMasterConfiguration,
ResourceID resourceId,
JobGraph jobGraph,
HighAvailabilityServices highAvailabilityService,
SlotPoolServiceSchedulerFactory slotPoolServiceSchedulerFactory,
JobManagerSharedServices jobManagerSharedServices,
HeartbeatServices heartbeatServices,
JobManagerJobMetricGroupFactory jobMetricGroupFactory,
OnCompletionActions jobCompletionActions,
FatalErrorHandler fatalErrorHandler,
ClassLoader userCodeLoader,
ShuffleMaster> shuffleMaster,
PartitionTrackerFactory partitionTrackerFactory,
ExecutionDeploymentTracker executionDeploymentTracker,
ExecutionDeploymentReconciler.Factory executionDeploymentReconcilerFactory,
BlocklistHandler.Factory blocklistHandlerFactory,
Collection failureEnrichers,
long initializationTimestamp)
throws Exception {
super(
rpcService,
RpcServiceUtils.createRandomName(JOB_MANAGER_NAME),
jobMasterId,
MdcUtils.asContextData(jobGraph.getJobID()));
final ExecutionDeploymentReconciliationHandler executionStateReconciliationHandler =
new ExecutionDeploymentReconciliationHandler() {
@Override
public void onMissingDeploymentsOf(
Collection executionAttemptIds, ResourceID host) {
log.debug(
"Failing deployments {} due to no longer being deployed.",
executionAttemptIds);
for (ExecutionAttemptID executionAttemptId : executionAttemptIds) {
schedulerNG.updateTaskExecutionState(
new TaskExecutionState(
executionAttemptId,
ExecutionState.FAILED,
new FlinkException(
String.format(
"Execution %s is unexpectedly no longer running on task executor %s.",
executionAttemptId, host))));
}
}
@Override
public void onUnknownDeploymentsOf(
Collection executionAttemptIds, ResourceID host) {
log.debug(
"Canceling left-over deployments {} on task executor {}.",
executionAttemptIds,
host);
for (ExecutionAttemptID executionAttemptId : executionAttemptIds) {
TaskManagerRegistration taskManagerRegistration =
registeredTaskManagers.get(host);
if (taskManagerRegistration != null) {
taskManagerRegistration
.getTaskExecutorGateway()
.cancelTask(executionAttemptId, rpcTimeout);
}
}
}
};
final String jobName = jobGraph.getName();
final JobID jid = jobGraph.getJobID();
log.info("Initializing job '{}' ({}).", jobName, jid);
this.executionDeploymentTracker = executionDeploymentTracker;
this.executionDeploymentReconciler =
executionDeploymentReconcilerFactory.create(executionStateReconciliationHandler);
this.jobMasterConfiguration = checkNotNull(jobMasterConfiguration);
this.resourceId = checkNotNull(resourceId);
this.jobGraph = checkNotNull(jobGraph);
this.rpcTimeout = jobMasterConfiguration.getRpcTimeout();
this.highAvailabilityServices = checkNotNull(highAvailabilityService);
this.blobWriter = jobManagerSharedServices.getBlobWriter();
this.futureExecutor =
MdcUtils.scopeToJob(jid, jobManagerSharedServices.getFutureExecutor());
this.ioExecutor = MdcUtils.scopeToJob(jid, jobManagerSharedServices.getIoExecutor());
this.jobCompletionActions = checkNotNull(jobCompletionActions);
this.fatalErrorHandler = checkNotNull(fatalErrorHandler);
this.userCodeLoader = checkNotNull(userCodeLoader);
this.initializationTimestamp = initializationTimestamp;
this.retrieveTaskManagerHostName =
jobMasterConfiguration
.getConfiguration()
.get(JobManagerOptions.RETRIEVE_TASK_MANAGER_HOSTNAME);
resourceManagerLeaderRetriever =
highAvailabilityServices.getResourceManagerLeaderRetriever();
this.registeredTaskManagers = new HashMap<>();
this.blocklistHandler =
blocklistHandlerFactory.create(
new JobMasterBlocklistContext(),
this::getNodeIdOfTaskManager,
getMainThreadExecutor(),
log);
this.slotPoolService =
checkNotNull(slotPoolServiceSchedulerFactory)
.createSlotPoolService(
jid,
createDeclarativeSlotPoolFactory(
jobMasterConfiguration.getConfiguration()),
getMainThreadExecutor());
this.partitionTracker =
checkNotNull(partitionTrackerFactory)
.create(
resourceID -> {
return Optional.ofNullable(
registeredTaskManagers.get(resourceID))
.map(TaskManagerRegistration::getTaskExecutorGateway);
});
this.shuffleMaster = checkNotNull(shuffleMaster);
this.jobManagerJobMetricGroup = jobMetricGroupFactory.create(jobGraph);
this.jobStatusListener = new JobManagerJobStatusListener();
this.failureEnrichers = checkNotNull(failureEnrichers);
this.schedulerNG =
createScheduler(
slotPoolServiceSchedulerFactory,
executionDeploymentTracker,
jobManagerJobMetricGroup,
jobStatusListener);
this.heartbeatServices = checkNotNull(heartbeatServices);
this.taskManagerHeartbeatManager = NoOpHeartbeatManager.getInstance();
this.resourceManagerHeartbeatManager = NoOpHeartbeatManager.getInstance();
this.resourceManagerConnection = null;
this.establishedResourceManagerConnection = null;
this.accumulators = new HashMap<>();
}
private SchedulerNG createScheduler(
SlotPoolServiceSchedulerFactory slotPoolServiceSchedulerFactory,
ExecutionDeploymentTracker executionDeploymentTracker,
JobManagerJobMetricGroup jobManagerJobMetricGroup,
JobStatusListener jobStatusListener)
throws Exception {
final SchedulerNG scheduler =
slotPoolServiceSchedulerFactory.createScheduler(
log,
jobGraph,
ioExecutor,
jobMasterConfiguration.getConfiguration(),
slotPoolService,
futureExecutor,
userCodeLoader,
highAvailabilityServices.getCheckpointRecoveryFactory(),
rpcTimeout,
blobWriter,
jobManagerJobMetricGroup,
jobMasterConfiguration.getSlotRequestTimeout(),
shuffleMaster,
partitionTracker,
executionDeploymentTracker,
initializationTimestamp,
getMainThreadExecutor(),
fatalErrorHandler,
jobStatusListener,
failureEnrichers,
blocklistHandler::addNewBlockedNodes);
return scheduler;
}
private HeartbeatManager createResourceManagerHeartbeatManager(
HeartbeatServices heartbeatServices) {
return heartbeatServices.createHeartbeatManager(
resourceId, new ResourceManagerHeartbeatListener(), getMainThreadExecutor(), log);
}
private HeartbeatManager
createTaskManagerHeartbeatManager(HeartbeatServices heartbeatServices) {
return heartbeatServices.createHeartbeatManagerSender(
resourceId, new TaskManagerHeartbeatListener(), getMainThreadExecutor(), log);
}
private DeclarativeSlotPoolFactory createDeclarativeSlotPoolFactory(
Configuration configuration) {
if (BlocklistUtils.isBlocklistEnabled(configuration)) {
return new BlocklistDeclarativeSlotPoolFactory(blocklistHandler::isBlockedTaskManager);
} else {
return new DefaultDeclarativeSlotPoolFactory();
}
}
// ----------------------------------------------------------------------------------------------
// Lifecycle management
// ----------------------------------------------------------------------------------------------
@Override
protected void onStart() throws JobMasterException {
try {
startJobExecution();
} catch (Exception e) {
final JobMasterException jobMasterException =
new JobMasterException("Could not start the JobMaster.", e);
handleJobMasterError(jobMasterException);
throw jobMasterException;
}
}
/** Suspend the job and shutdown all other services including rpc. */
@Override
public CompletableFuture onStop() {
log.info(
"Stopping the JobMaster for job '{}' ({}).",
jobGraph.getName(),
jobGraph.getJobID());
// make sure there is a graceful exit
return stopJobExecution(
new FlinkException(
String.format(
"Stopping JobMaster for job '%s' (%s).",
jobGraph.getName(), jobGraph.getJobID())))
.exceptionally(
exception -> {
throw new CompletionException(
new JobMasterException(
"Could not properly stop the JobMaster.", exception));
});
}
// ----------------------------------------------------------------------------------------------
// RPC methods
// ----------------------------------------------------------------------------------------------
@Override
public CompletableFuture cancel(Duration timeout) {
schedulerNG.cancel();
return CompletableFuture.completedFuture(Acknowledge.get());
}
/**
* Updates the task execution state for a given task.
*
* @param taskExecutionState New task execution state for a given task
* @return Acknowledge the task execution state update
*/
@Override
public CompletableFuture updateTaskExecutionState(
final TaskExecutionState taskExecutionState) {
FlinkException taskExecutionException;
try {
checkNotNull(taskExecutionState, "taskExecutionState");
if (schedulerNG.updateTaskExecutionState(taskExecutionState)) {
return CompletableFuture.completedFuture(Acknowledge.get());
} else {
taskExecutionException =
new ExecutionGraphException(
"The execution attempt "
+ taskExecutionState.getID()
+ " was not found.");
}
} catch (Exception e) {
taskExecutionException =
new JobMasterException(
"Could not update the state of task execution for JobMaster.", e);
handleJobMasterError(taskExecutionException);
}
return FutureUtils.completedExceptionally(taskExecutionException);
}
@Override
public void notifyEndOfData(final ExecutionAttemptID executionAttempt) {
schedulerNG.notifyEndOfData(executionAttempt);
}
@Override
public CompletableFuture requestNextInputSplit(
final JobVertexID vertexID, final ExecutionAttemptID executionAttempt) {
try {
return CompletableFuture.completedFuture(
schedulerNG.requestNextInputSplit(vertexID, executionAttempt));
} catch (IOException e) {
log.warn("Error while requesting next input split", e);
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture requestPartitionState(
final IntermediateDataSetID intermediateResultId,
final ResultPartitionID resultPartitionId) {
try {
return CompletableFuture.completedFuture(
schedulerNG.requestPartitionState(intermediateResultId, resultPartitionId));
} catch (PartitionProducerDisposedException e) {
log.info("Error while requesting partition state", e);
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture disconnectTaskManager(
final ResourceID resourceID, final Exception cause) {
taskManagerHeartbeatManager.unmonitorTarget(resourceID);
slotPoolService.releaseTaskManager(resourceID, cause);
partitionTracker.stopTrackingPartitionsFor(resourceID);
TaskManagerRegistration taskManagerRegistration = registeredTaskManagers.remove(resourceID);
if (taskManagerRegistration != null) {
log.info(
"Disconnect TaskExecutor {} because: {}",
resourceID.getStringWithMetadata(),
cause.getMessage(),
ExceptionUtils.returnExceptionIfUnexpected(cause.getCause()));
ExceptionUtils.logExceptionIfExcepted(cause.getCause(), log);
taskManagerRegistration
.getTaskExecutorGateway()
.disconnectJobManager(jobGraph.getJobID(), cause);
}
return CompletableFuture.completedFuture(Acknowledge.get());
}
// TODO: This method needs a leader session ID
@Override
public void acknowledgeCheckpoint(
final JobID jobID,
final ExecutionAttemptID executionAttemptID,
final long checkpointId,
final CheckpointMetrics checkpointMetrics,
@Nullable final SerializedValue checkpointState) {
schedulerNG.acknowledgeCheckpoint(
jobID,
executionAttemptID,
checkpointId,
checkpointMetrics,
deserializeTaskStateSnapshot(checkpointState, getClass().getClassLoader()));
}
@Override
public void reportCheckpointMetrics(
JobID jobID,
ExecutionAttemptID executionAttemptID,
long checkpointId,
CheckpointMetrics checkpointMetrics) {
schedulerNG.reportCheckpointMetrics(
jobID, executionAttemptID, checkpointId, checkpointMetrics);
}
@Override
public void reportInitializationMetrics(
JobID jobId,
ExecutionAttemptID executionAttemptId,
SubTaskInitializationMetrics initializationMetrics) {
schedulerNG.reportInitializationMetrics(jobId, executionAttemptId, initializationMetrics);
}
// TODO: This method needs a leader session ID
@Override
public void declineCheckpoint(DeclineCheckpoint decline) {
schedulerNG.declineCheckpoint(decline);
}
@Override
public CompletableFuture sendOperatorEventToCoordinator(
final ExecutionAttemptID task,
final OperatorID operatorID,
final SerializedValue serializedEvent) {
try {
final OperatorEvent evt = serializedEvent.deserializeValue(userCodeLoader);
schedulerNG.deliverOperatorEventToCoordinator(task, operatorID, evt);
return CompletableFuture.completedFuture(Acknowledge.get());
} catch (Exception e) {
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture sendRequestToCoordinator(
OperatorID operatorID, SerializedValue serializedRequest) {
try {
final CoordinationRequest request = serializedRequest.deserializeValue(userCodeLoader);
return schedulerNG.deliverCoordinationRequestToCoordinator(operatorID, request);
} catch (Exception e) {
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture requestKvStateLocation(
final JobID jobId, final String registrationName) {
try {
return CompletableFuture.completedFuture(
schedulerNG.requestKvStateLocation(jobId, registrationName));
} catch (UnknownKvStateLocation | FlinkJobNotFoundException e) {
log.info("Error while request key-value state location", e);
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture notifyKvStateRegistered(
final JobID jobId,
final JobVertexID jobVertexId,
final KeyGroupRange keyGroupRange,
final String registrationName,
final KvStateID kvStateId,
final InetSocketAddress kvStateServerAddress) {
try {
schedulerNG.notifyKvStateRegistered(
jobId,
jobVertexId,
keyGroupRange,
registrationName,
kvStateId,
kvStateServerAddress);
return CompletableFuture.completedFuture(Acknowledge.get());
} catch (FlinkJobNotFoundException e) {
log.info("Error while receiving notification about key-value state registration", e);
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture notifyKvStateUnregistered(
JobID jobId,
JobVertexID jobVertexId,
KeyGroupRange keyGroupRange,
String registrationName) {
try {
schedulerNG.notifyKvStateUnregistered(
jobId, jobVertexId, keyGroupRange, registrationName);
return CompletableFuture.completedFuture(Acknowledge.get());
} catch (FlinkJobNotFoundException e) {
log.info("Error while receiving notification about key-value state de-registration", e);
return FutureUtils.completedExceptionally(e);
}
}
@Override
public CompletableFuture> offerSlots(
final ResourceID taskManagerId,
final Collection slots,
final Duration timeout) {
TaskManagerRegistration taskManagerRegistration = registeredTaskManagers.get(taskManagerId);
if (taskManagerRegistration == null) {
return FutureUtils.completedExceptionally(
new Exception("Unknown TaskManager " + taskManagerId));
}
final RpcTaskManagerGateway rpcTaskManagerGateway =
new RpcTaskManagerGateway(
taskManagerRegistration.getTaskExecutorGateway(), getFencingToken());
return CompletableFuture.completedFuture(
slotPoolService.offerSlots(
taskManagerRegistration.getTaskManagerLocation(),
rpcTaskManagerGateway,
slots));
}
@Override
public void failSlot(
final ResourceID taskManagerId,
final AllocationID allocationId,
final Exception cause) {
if (registeredTaskManagers.containsKey(taskManagerId)) {
internalFailAllocation(taskManagerId, allocationId, cause);
} else {
log.warn(
"Cannot fail slot "
+ allocationId
+ " because the TaskManager "
+ taskManagerId
+ " is unknown.");
}
}
private void internalFailAllocation(
@Nullable ResourceID resourceId, AllocationID allocationId, Exception cause) {
final Optional resourceIdOptional =
slotPoolService.failAllocation(resourceId, allocationId, cause);
resourceIdOptional.ifPresent(
taskManagerId -> {
if (!partitionTracker.isTrackingPartitionsFor(taskManagerId)) {
releaseEmptyTaskManager(taskManagerId);
}
});
}
private void releaseEmptyTaskManager(ResourceID resourceId) {
disconnectTaskManager(
resourceId,
new FlinkException(
String.format(
"No more slots registered at JobMaster %s.",
resourceId.getStringWithMetadata())));
}
@Override
public CompletableFuture registerTaskManager(
final JobID jobId,
final TaskManagerRegistrationInformation taskManagerRegistrationInformation,
final Duration timeout) {
if (!jobGraph.getJobID().equals(jobId)) {
log.debug(
"Rejecting TaskManager registration attempt because of wrong job id {}.",
jobId);
return CompletableFuture.completedFuture(
new JMTMRegistrationRejection(
String.format(
"The JobManager is not responsible for job %s. Maybe the TaskManager used outdated connection information.",
jobId)));
}
final TaskManagerLocation taskManagerLocation;
try {
taskManagerLocation =
resolveTaskManagerLocation(
taskManagerRegistrationInformation.getUnresolvedTaskManagerLocation());
} catch (FlinkException exception) {
log.error("Could not accept TaskManager registration.", exception);
return CompletableFuture.completedFuture(new RegistrationResponse.Failure(exception));
}
final ResourceID taskManagerId = taskManagerLocation.getResourceID();
final UUID sessionId = taskManagerRegistrationInformation.getTaskManagerSession();
final TaskManagerRegistration taskManagerRegistration =
registeredTaskManagers.get(taskManagerId);
if (taskManagerRegistration != null) {
if (taskManagerRegistration.getSessionId().equals(sessionId)) {
log.debug(
"Ignoring registration attempt of TaskManager {} with the same session id {}.",
taskManagerId,
sessionId);
final RegistrationResponse response = new JMTMRegistrationSuccess(resourceId);
return CompletableFuture.completedFuture(response);
} else {
disconnectTaskManager(
taskManagerId,
new FlinkException(
String.format(
"A registered TaskManager %s re-registered with a new session id. This indicates a restart of the TaskManager. Closing the old connection.",
taskManagerId)));
}
}
CompletableFuture registrationResponseFuture =
getRpcService()
.connect(
taskManagerRegistrationInformation.getTaskManagerRpcAddress(),
TaskExecutorGateway.class)
.handleAsync(
(TaskExecutorGateway taskExecutorGateway, Throwable throwable) -> {
if (throwable != null) {
return new RegistrationResponse.Failure(throwable);
}
slotPoolService.registerTaskManager(taskManagerId);
registeredTaskManagers.put(
taskManagerId,
TaskManagerRegistration.create(
taskManagerLocation,
taskExecutorGateway,
sessionId));
// monitor the task manager as heartbeat target
taskManagerHeartbeatManager.monitorTarget(
taskManagerId,
new TaskExecutorHeartbeatSender(taskExecutorGateway));
return new JMTMRegistrationSuccess(resourceId);
},
getMainThreadExecutor());
if (fetchAndRetainPartitions) {
registrationResponseFuture.whenComplete(
(ignored, throwable) ->
fetchAndRetainPartitionWithMetricsOnTaskManager(taskManagerId));
}
return registrationResponseFuture;
}
@Nonnull
private TaskManagerLocation resolveTaskManagerLocation(
UnresolvedTaskManagerLocation unresolvedTaskManagerLocation) throws FlinkException {
try {
if (retrieveTaskManagerHostName) {
return TaskManagerLocation.fromUnresolvedLocation(
unresolvedTaskManagerLocation, ResolutionMode.RETRIEVE_HOST_NAME);
} else {
return TaskManagerLocation.fromUnresolvedLocation(
unresolvedTaskManagerLocation, ResolutionMode.USE_IP_ONLY);
}
} catch (Throwable throwable) {
final String errMsg =
String.format(
"TaskManager address %s cannot be resolved. %s",
unresolvedTaskManagerLocation.getExternalAddress(),
throwable.getMessage());
throw new FlinkException(errMsg, throwable);
}
}
@Override
public void disconnectResourceManager(
final ResourceManagerId resourceManagerId, final Exception cause) {
if (isConnectingToResourceManager(resourceManagerId)) {
reconnectToResourceManager(cause);
}
}
private boolean isConnectingToResourceManager(ResourceManagerId resourceManagerId) {
return resourceManagerAddress != null
&& resourceManagerAddress.getResourceManagerId().equals(resourceManagerId);
}
@Override
public CompletableFuture heartbeatFromTaskManager(
final ResourceID resourceID, TaskExecutorToJobManagerHeartbeatPayload payload) {
return taskManagerHeartbeatManager.receiveHeartbeat(resourceID, payload);
}
@Override
public CompletableFuture heartbeatFromResourceManager(final ResourceID resourceID) {
return resourceManagerHeartbeatManager.requestHeartbeat(resourceID, null);
}
@Override
public CompletableFuture requestJobStatus(Duration timeout) {
return CompletableFuture.completedFuture(schedulerNG.requestJobStatus());
}
@Override
public CompletableFuture requestJob(Duration timeout) {
return CompletableFuture.completedFuture(schedulerNG.requestJob());
}
@Override
public CompletableFuture requestCheckpointStats(Duration timeout) {
return CompletableFuture.completedFuture(schedulerNG.requestCheckpointStats());
}
@Override
public CompletableFuture triggerCheckpoint(
final CheckpointType checkpointType, final Duration timeout) {
return schedulerNG.triggerCheckpoint(checkpointType);
}
@Override
public CompletableFuture triggerSavepoint(
@Nullable final String targetDirectory,
final boolean cancelJob,
final SavepointFormatType formatType,
final Duration timeout) {
return schedulerNG.triggerSavepoint(targetDirectory, cancelJob, formatType);
}
@Override
public CompletableFuture stopWithSavepoint(
@Nullable final String targetDirectory,
final SavepointFormatType formatType,
final boolean terminate,
final Duration timeout) {
return schedulerNG.stopWithSavepoint(targetDirectory, terminate, formatType);
}
@Override
public void notifyNotEnoughResourcesAvailable(
Collection acquiredResources) {
slotPoolService.notifyNotEnoughResourcesAvailable(acquiredResources);
}
@Override
public CompletableFuture
© 2015 - 2025 Weber Informatics LLC | Privacy Policy