use of org.apache.storm.scheduler.SupervisorDetails in project storm by apache.
the class Nimbus method readAllSupervisorDetails.
/**
* @param superToDeadPorts dead ports on the supervisor
* @param topologies all of the topologies
* @param missingAssignmentTopologies topologies that need assignments
* @return a map: {supervisor-id SupervisorDetails}
*/
private Map<String, SupervisorDetails> readAllSupervisorDetails(Map<String, Set<Long>> superToDeadPorts, Topologies topologies, Collection<String> missingAssignmentTopologies) {
Map<String, SupervisorDetails> ret = new HashMap<>();
IStormClusterState state = stormClusterState;
Map<String, SupervisorInfo> superInfos = state.allSupervisorInfo();
List<SupervisorDetails> superDetails = new ArrayList<>();
for (Entry<String, SupervisorInfo> entry : superInfos.entrySet()) {
SupervisorInfo info = entry.getValue();
superDetails.add(new SupervisorDetails(entry.getKey(), info.get_meta(), info.get_resources_map()));
}
// Note that allSlotsAvailableForScheduling
// only uses the supervisor-details. The rest of the arguments
// are there to satisfy the INimbus interface.
Map<String, Set<Long>> superToPorts = new HashMap<>();
for (WorkerSlot slot : inimbus.allSlotsAvailableForScheduling(superDetails, topologies, new HashSet<>(missingAssignmentTopologies))) {
String superId = slot.getNodeId();
Set<Long> ports = superToPorts.get(superId);
if (ports == null) {
ports = new HashSet<>();
superToPorts.put(superId, ports);
}
ports.add((long) slot.getPort());
}
for (Entry<String, SupervisorInfo> entry : superInfos.entrySet()) {
String superId = entry.getKey();
SupervisorInfo info = entry.getValue();
String hostname = info.get_hostname();
// Hide the dead-ports from the all-ports
// these dead-ports can be reused in next round of assignments
Set<Long> deadPorts = superToDeadPorts.get(superId);
Set<Long> allPorts = superToPorts.get(superId);
if (allPorts == null) {
allPorts = new HashSet<>();
} else {
allPorts = new HashSet<>(allPorts);
}
if (deadPorts != null) {
allPorts.removeAll(deadPorts);
}
ret.put(superId, new SupervisorDetails(superId, hostname, info.get_scheduler_meta(), allPorts, info.get_resources_map()));
}
return ret;
}
use of org.apache.storm.scheduler.SupervisorDetails in project storm by apache.
the class Nimbus method mkAssignments.
private void mkAssignments(String scratchTopoId) throws Exception {
if (!isLeader()) {
LOG.info("not a leader, skipping assignments");
return;
}
// get existing assignment (just the topologyToExecutorToNodePort map) -> default to {}
// filter out ones which have a executor timeout
// figure out available slots on cluster. add to that the used valid slots to get total slots. figure out how many executors should be in each slot (e.g., 4, 4, 4, 5)
// only keep existing slots that satisfy one of those slots. for rest, reassign them across remaining slots
// edge case for slots with no executor timeout but with supervisor timeout... just treat these as valid slots that can be reassigned to. worst comes to worse the executor will timeout and won't assign here next time around
IStormClusterState state = stormClusterState;
//read all the topologies
Map<String, StormBase> bases;
Map<String, TopologyDetails> tds = new HashMap<>();
synchronized (submitLock) {
bases = state.topologyBases();
for (Iterator<Entry<String, StormBase>> it = bases.entrySet().iterator(); it.hasNext(); ) {
Entry<String, StormBase> entry = it.next();
String id = entry.getKey();
try {
tds.put(id, readTopologyDetails(id, entry.getValue()));
} catch (KeyNotFoundException e) {
//A race happened and it is probably not running
it.remove();
}
}
}
Topologies topologies = new Topologies(tds);
List<String> assignedTopologyIds = state.assignments(null);
Map<String, Assignment> existingAssignments = new HashMap<>();
for (String id : assignedTopologyIds) {
// will be treated as free slot in the scheduler code.
if (!id.equals(scratchTopoId)) {
existingAssignments.put(id, state.assignmentInfo(id, null));
}
}
// make the new assignments for topologies
Map<String, SchedulerAssignment> newSchedulerAssignments = null;
synchronized (schedLock) {
newSchedulerAssignments = computeNewSchedulerAssignments(existingAssignments, topologies, bases, scratchTopoId);
Map<String, Map<List<Long>, List<Object>>> topologyToExecutorToNodePort = computeNewTopoToExecToNodePort(newSchedulerAssignments, existingAssignments);
for (String id : assignedTopologyIds) {
if (!topologyToExecutorToNodePort.containsKey(id)) {
topologyToExecutorToNodePort.put(id, null);
}
}
Map<String, Map<List<Object>, List<Double>>> newAssignedWorkerToResources = computeTopoToNodePortToResources(newSchedulerAssignments);
int nowSecs = Time.currentTimeSecs();
Map<String, SupervisorDetails> basicSupervisorDetailsMap = basicSupervisorDetailsMap(state);
//construct the final Assignments by adding start-times etc into it
Map<String, Assignment> newAssignments = new HashMap<>();
for (Entry<String, Map<List<Long>, List<Object>>> entry : topologyToExecutorToNodePort.entrySet()) {
String topoId = entry.getKey();
Map<List<Long>, List<Object>> execToNodePort = entry.getValue();
Assignment existingAssignment = existingAssignments.get(topoId);
Set<String> allNodes = new HashSet<>();
if (execToNodePort != null) {
for (List<Object> nodePort : execToNodePort.values()) {
allNodes.add((String) nodePort.get(0));
}
}
Map<String, String> allNodeHost = new HashMap<>();
if (existingAssignment != null) {
allNodeHost.putAll(existingAssignment.get_node_host());
}
for (String node : allNodes) {
String host = inimbus.getHostName(basicSupervisorDetailsMap, node);
if (host != null) {
allNodeHost.put(node, host);
}
}
Map<List<Long>, NodeInfo> execNodeInfo = null;
if (existingAssignment != null) {
execNodeInfo = existingAssignment.get_executor_node_port();
}
List<List<Long>> reassignExecutors = changedExecutors(execNodeInfo, execToNodePort);
Map<List<Long>, Long> startTimes = new HashMap<>();
if (existingAssignment != null) {
startTimes.putAll(existingAssignment.get_executor_start_time_secs());
}
for (List<Long> id : reassignExecutors) {
startTimes.put(id, (long) nowSecs);
}
Map<List<Object>, List<Double>> workerToResources = newAssignedWorkerToResources.get(topoId);
Assignment newAssignment = new Assignment((String) conf.get(Config.STORM_LOCAL_DIR));
Map<String, String> justAssignedKeys = new HashMap<>(allNodeHost);
//Modifies justAssignedKeys
justAssignedKeys.keySet().retainAll(allNodes);
newAssignment.set_node_host(justAssignedKeys);
//convert NodePort to NodeInfo (again!!!).
Map<List<Long>, NodeInfo> execToNodeInfo = new HashMap<>();
for (Entry<List<Long>, List<Object>> execAndNodePort : execToNodePort.entrySet()) {
List<Object> nodePort = execAndNodePort.getValue();
NodeInfo ni = new NodeInfo();
ni.set_node((String) nodePort.get(0));
ni.add_to_port((Long) nodePort.get(1));
execToNodeInfo.put(execAndNodePort.getKey(), ni);
}
newAssignment.set_executor_node_port(execToNodeInfo);
newAssignment.set_executor_start_time_secs(startTimes);
//do another conversion (lets just make this all common)
Map<NodeInfo, WorkerResources> workerResources = new HashMap<>();
for (Entry<List<Object>, List<Double>> wr : workerToResources.entrySet()) {
List<Object> nodePort = wr.getKey();
NodeInfo ni = new NodeInfo();
ni.set_node((String) nodePort.get(0));
ni.add_to_port((Long) nodePort.get(1));
List<Double> r = wr.getValue();
WorkerResources resources = new WorkerResources();
resources.set_mem_on_heap(r.get(0));
resources.set_mem_off_heap(r.get(1));
resources.set_cpu(r.get(2));
workerResources.put(ni, resources);
}
newAssignment.set_worker_resources(workerResources);
newAssignments.put(topoId, newAssignment);
}
if (!newAssignments.equals(existingAssignments)) {
LOG.debug("RESETTING id->resources and id->worker-resources cache!");
idToResources.set(new HashMap<>());
idToWorkerResources.set(new HashMap<>());
}
// only log/set when there's been a change to the assignment
for (Entry<String, Assignment> entry : newAssignments.entrySet()) {
String topoId = entry.getKey();
Assignment assignment = entry.getValue();
Assignment existingAssignment = existingAssignments.get(topoId);
//NOT Used TopologyDetails topologyDetails = topologies.getById(topoId);
if (assignment.equals(existingAssignment)) {
LOG.debug("Assignment for {} hasn't changed", topoId);
} else {
LOG.info("Setting new assignment for topology id {}: {}", topoId, assignment);
state.setAssignment(topoId, assignment);
}
}
Map<String, Collection<WorkerSlot>> addedSlots = new HashMap<>();
for (Entry<String, Assignment> entry : newAssignments.entrySet()) {
String topoId = entry.getKey();
Assignment assignment = entry.getValue();
Assignment existingAssignment = existingAssignments.get(topoId);
if (existingAssignment == null) {
existingAssignment = new Assignment();
existingAssignment.set_executor_node_port(new HashMap<>());
existingAssignment.set_executor_start_time_secs(new HashMap<>());
}
Set<WorkerSlot> newSlots = newlyAddedSlots(existingAssignment, assignment);
addedSlots.put(topoId, newSlots);
}
inimbus.assignSlots(topologies, addedSlots);
}
}
use of org.apache.storm.scheduler.SupervisorDetails in project storm by apache.
the class Node method getAllNodesFrom.
public static Map<String, Node> getAllNodesFrom(Cluster cluster) {
Map<String, Node> nodeIdToNode = new HashMap<>();
for (SupervisorDetails sup : cluster.getSupervisors().values()) {
//Node ID and supervisor ID are the same.
String id = sup.getId();
boolean isAlive = !cluster.isBlackListed(id);
LOG.debug("Found a {} Node {} {}", isAlive ? "living" : "dead", id, sup.getAllPorts());
nodeIdToNode.put(id, new Node(id, sup.getAllPorts(), isAlive));
}
for (Entry<String, SchedulerAssignment> entry : cluster.getAssignments().entrySet()) {
String topId = entry.getValue().getTopologyId();
for (WorkerSlot ws : entry.getValue().getSlots()) {
String id = ws.getNodeId();
Node node = nodeIdToNode.get(id);
if (node == null) {
LOG.debug("Found an assigned slot on a dead supervisor {}", ws);
node = new Node(id, null, false);
nodeIdToNode.put(id, node);
}
if (!node.isAlive()) {
//The supervisor on the node down so add an orphaned slot to hold the unsupervised worker
node.addOrphanedSlot(ws);
}
if (node.assignInternal(ws, topId, true)) {
LOG.warn("Bad scheduling state for topology [" + topId + "], the slot " + ws + " assigned to multiple workers, un-assigning everything...");
node.free(ws, cluster, true);
}
}
}
return nodeIdToNode;
}
use of org.apache.storm.scheduler.SupervisorDetails in project storm by apache.
the class RAS_Nodes method getAllNodesFrom.
public static Map<String, RAS_Node> getAllNodesFrom(Cluster cluster, Topologies topologies) {
//A map of node ids to node objects
Map<String, RAS_Node> nodeIdToNode = new HashMap<String, RAS_Node>();
//A map of assignments organized by node with the following format:
//{nodeId -> {topologyId -> {workerId -> {execs}}}}
Map<String, Map<String, Map<String, Collection<ExecutorDetails>>>> assignmentRelationshipMap = new HashMap<String, Map<String, Map<String, Collection<ExecutorDetails>>>>();
Map<String, Map<String, WorkerSlot>> workerIdToWorker = new HashMap<String, Map<String, WorkerSlot>>();
for (SchedulerAssignment assignment : cluster.getAssignments().values()) {
String topId = assignment.getTopologyId();
for (Map.Entry<WorkerSlot, Collection<ExecutorDetails>> entry : assignment.getSlotToExecutors().entrySet()) {
WorkerSlot slot = entry.getKey();
String nodeId = slot.getNodeId();
Collection<ExecutorDetails> execs = entry.getValue();
if (!assignmentRelationshipMap.containsKey(nodeId)) {
assignmentRelationshipMap.put(nodeId, new HashMap<String, Map<String, Collection<ExecutorDetails>>>());
workerIdToWorker.put(nodeId, new HashMap<String, WorkerSlot>());
}
workerIdToWorker.get(nodeId).put(slot.getId(), slot);
if (!assignmentRelationshipMap.get(nodeId).containsKey(topId)) {
assignmentRelationshipMap.get(nodeId).put(topId, new HashMap<String, Collection<ExecutorDetails>>());
}
if (!assignmentRelationshipMap.get(nodeId).get(topId).containsKey(slot.getId())) {
assignmentRelationshipMap.get(nodeId).get(topId).put(slot.getId(), new LinkedList<ExecutorDetails>());
}
assignmentRelationshipMap.get(nodeId).get(topId).get(slot.getId()).addAll(execs);
}
}
for (SupervisorDetails sup : cluster.getSupervisors().values()) {
//Initialize a worker slot for every port even if there is no assignment to it
for (int port : sup.getAllPorts()) {
WorkerSlot worker = new WorkerSlot(sup.getId(), port);
if (!workerIdToWorker.containsKey(sup.getId())) {
workerIdToWorker.put(sup.getId(), new HashMap<String, WorkerSlot>());
}
if (!workerIdToWorker.get(sup.getId()).containsKey(worker.getId())) {
workerIdToWorker.get(sup.getId()).put(worker.getId(), worker);
}
}
nodeIdToNode.put(sup.getId(), new RAS_Node(sup.getId(), sup, cluster, topologies, workerIdToWorker.get(sup.getId()), assignmentRelationshipMap.get(sup.getId())));
}
//Add in supervisors that might have crashed but workers are still alive
for (Map.Entry<String, Map<String, Map<String, Collection<ExecutorDetails>>>> entry : assignmentRelationshipMap.entrySet()) {
String nodeId = entry.getKey();
Map<String, Map<String, Collection<ExecutorDetails>>> assignments = entry.getValue();
if (!nodeIdToNode.containsKey(nodeId)) {
LOG.info("Found an assigned slot(s) on a dead supervisor {} with assignments {}", nodeId, assignments);
nodeIdToNode.put(nodeId, new RAS_Node(nodeId, null, cluster, topologies, workerIdToWorker.get(nodeId), assignments));
}
}
return nodeIdToNode;
}
use of org.apache.storm.scheduler.SupervisorDetails in project storm by apache.
the class Nimbus method computeNewSchedulerAssignments.
private Map<String, SchedulerAssignment> computeNewSchedulerAssignments(Map<String, Assignment> existingAssignments, Topologies topologies, Map<String, StormBase> bases, String scratchTopologyId) throws KeyNotFoundException, AuthorizationException, InvalidTopologyException, IOException {
Map<String, Set<List<Integer>>> topoToExec = computeTopologyToExecutors(bases);
updateAllHeartbeats(existingAssignments, topoToExec);
Map<String, Set<List<Integer>>> topoToAliveExecutors = computeTopologyToAliveExecutors(existingAssignments, topologies, topoToExec, scratchTopologyId);
Map<String, Set<Long>> supervisorToDeadPorts = computeSupervisorToDeadPorts(existingAssignments, topoToExec, topoToAliveExecutors);
Map<String, SchedulerAssignmentImpl> topoToSchedAssignment = computeTopologyToSchedulerAssignment(existingAssignments, topoToAliveExecutors);
Set<String> missingAssignmentTopologies = new HashSet<>();
for (TopologyDetails topo : topologies.getTopologies()) {
String id = topo.getId();
Set<List<Integer>> allExecs = topoToExec.get(id);
Set<List<Integer>> aliveExecs = topoToAliveExecutors.get(id);
int numDesiredWorkers = topo.getNumWorkers();
int numAssignedWorkers = numUsedWorkers(topoToSchedAssignment.get(id));
if (allExecs == null || allExecs.isEmpty() || !allExecs.equals(aliveExecs) || numDesiredWorkers > numAssignedWorkers) {
//We have something to schedule...
missingAssignmentTopologies.add(id);
}
}
Map<String, SupervisorDetails> supervisors = readAllSupervisorDetails(supervisorToDeadPorts, topologies, missingAssignmentTopologies);
Cluster cluster = new Cluster(inimbus, supervisors, topoToSchedAssignment, conf);
cluster.setStatusMap(idToSchedStatus.get());
scheduler.schedule(topologies, cluster);
//merge with existing statuses
idToSchedStatus.set(merge(idToSchedStatus.get(), cluster.getStatusMap()));
nodeIdToResources.set(cluster.getSupervisorsResourcesMap());
if (!Utils.getBoolean(conf.get(Config.SCHEDULER_DISPLAY_RESOURCE), false)) {
cluster.updateAssignedMemoryForTopologyAndSupervisor(topologies);
}
// This is a hack for non-ras scheduler topology and worker resources
Map<String, TopologyResources> resources = new HashMap<>();
for (Entry<String, Double[]> uglyResources : cluster.getTopologyResourcesMap().entrySet()) {
Double[] r = uglyResources.getValue();
resources.put(uglyResources.getKey(), new TopologyResources(r[0], r[1], r[2], r[3], r[4], r[5]));
}
idToResources.getAndAccumulate(resources, (orig, update) -> merge(orig, update));
Map<String, Map<WorkerSlot, WorkerResources>> workerResources = new HashMap<>();
for (Entry<String, Map<WorkerSlot, Double[]>> uglyWorkerResources : cluster.getWorkerResourcesMap().entrySet()) {
Map<WorkerSlot, WorkerResources> slotToResources = new HashMap<>();
for (Entry<WorkerSlot, Double[]> uglySlotToResources : uglyWorkerResources.getValue().entrySet()) {
Double[] r = uglySlotToResources.getValue();
WorkerResources wr = new WorkerResources();
wr.set_mem_on_heap(r[0]);
wr.set_mem_off_heap(r[1]);
wr.set_cpu(r[2]);
slotToResources.put(uglySlotToResources.getKey(), wr);
}
workerResources.put(uglyWorkerResources.getKey(), slotToResources);
}
idToWorkerResources.getAndAccumulate(workerResources, (orig, update) -> merge(orig, update));
return cluster.getAssignments();
}
Aggregations