use of org.apache.hadoop.hive.llap.registry.LlapServiceInstance in project hive by apache.
the class LlapTaskSchedulerService method selectHost.
/**
* @param request the list of preferred hosts. null implies any host
* @return
*/
private SelectHostResult selectHost(TaskInfo request) {
String[] requestedHosts = request.requestedHosts;
String requestedHostsDebugStr = Arrays.toString(requestedHosts);
if (LOG.isDebugEnabled()) {
LOG.debug("selectingHost for task={} on hosts={}", request.task, requestedHostsDebugStr);
}
long schedulerAttemptTime = clock.getTime();
// Read-lock. Not updating any stats at the moment.
readLock.lock();
try {
boolean shouldDelayForLocality = request.shouldDelayForLocality(schedulerAttemptTime);
LOG.debug("ShouldDelayForLocality={} for task={} on hosts={}", shouldDelayForLocality, request.task, requestedHostsDebugStr);
if (requestedHosts != null && requestedHosts.length > 0) {
int prefHostCount = -1;
boolean requestedHostsWillBecomeAvailable = false;
for (String host : requestedHosts) {
prefHostCount++;
// Pick the first host always. Weak attempt at cache affinity.
Set<LlapServiceInstance> instances = activeInstances.getByHost(host);
if (!instances.isEmpty()) {
for (LlapServiceInstance inst : instances) {
NodeInfo nodeInfo = instanceToNodeMap.get(inst.getWorkerIdentity());
if (nodeInfo != null) {
if (nodeInfo.canAcceptTask()) {
// Successfully scheduled.
LOG.info("Assigning {} when looking for {}." + " local=true FirstRequestedHost={}, #prefLocations={}", nodeInfo.toShortString(), host, (prefHostCount == 0), requestedHosts.length);
return new SelectHostResult(nodeInfo);
} else {
// The node cannot accept a task at the moment.
if (shouldDelayForLocality) {
// Perform some checks on whether the node will become available or not.
if (request.shouldForceLocality()) {
requestedHostsWillBecomeAvailable = true;
} else {
if (nodeInfo.getEnableTime() > request.getLocalityDelayTimeout() && nodeInfo.isDisabled() && nodeInfo.hadCommFailure()) {
LOG.debug("Host={} will not become available within requested timeout", nodeInfo);
// This node will likely be activated after the task timeout expires.
} else {
// Worth waiting for the timeout.
requestedHostsWillBecomeAvailable = true;
}
}
}
}
} else {
LOG.warn("Null NodeInfo when attempting to get host with worker {}, and host {}", inst, host);
// Leave requestedHostWillBecomeAvailable as is. If some other host is found - delay,
// else ends up allocating to a random host immediately.
}
}
}
}
// Check if forcing the location is required.
if (shouldDelayForLocality) {
if (requestedHostsWillBecomeAvailable) {
if (LOG.isDebugEnabled()) {
LOG.debug("Delaying local allocation for [" + request.task + "] when trying to allocate on [" + requestedHostsDebugStr + "]" + ". ScheduleAttemptTime=" + schedulerAttemptTime + ", taskDelayTimeout=" + request.getLocalityDelayTimeout());
}
return SELECT_HOST_RESULT_DELAYED_LOCALITY;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping local allocation for [" + request.task + "] when trying to allocate on [" + requestedHostsDebugStr + "] since none of these hosts are part of the known list");
}
}
}
}
/* fall through - miss in locality or no locality-requested */
Collection<LlapServiceInstance> instances = activeInstances.getAllInstancesOrdered(true);
List<NodeInfo> allNodes = new ArrayList<>(instances.size());
List<NodeInfo> activeNodesWithFreeSlots = new ArrayList<>();
for (LlapServiceInstance inst : instances) {
if (inst instanceof InactiveServiceInstance) {
allNodes.add(null);
} else {
NodeInfo nodeInfo = instanceToNodeMap.get(inst.getWorkerIdentity());
if (nodeInfo == null) {
allNodes.add(null);
} else {
allNodes.add(nodeInfo);
if (nodeInfo.canAcceptTask()) {
activeNodesWithFreeSlots.add(nodeInfo);
}
}
}
}
if (allNodes.isEmpty()) {
return SELECT_HOST_RESULT_DELAYED_RESOURCES;
}
// no locality-requested, randomly pick a node containing free slots
if (requestedHosts == null || requestedHosts.length == 0) {
if (LOG.isDebugEnabled()) {
LOG.debug("No-locality requested. Selecting a random host for task={}", request.task);
}
return randomSelection(activeNodesWithFreeSlots);
}
// miss in locality request, try picking consistent location with fallback to random selection
final String firstRequestedHost = requestedHosts[0];
int requestedHostIdx = -1;
for (int i = 0; i < allNodes.size(); i++) {
NodeInfo nodeInfo = allNodes.get(i);
if (nodeInfo != null) {
if (nodeInfo.getHost().equals(firstRequestedHost)) {
requestedHostIdx = i;
break;
}
}
}
// TODO: At this point we don't know the slot number of the requested host, so can't rollover to next available
if (requestedHostIdx == -1) {
if (LOG.isDebugEnabled()) {
LOG.debug("Requested node [{}] in consistent order does not exist. Falling back to random selection for " + "request {}", firstRequestedHost, request);
}
return randomSelection(activeNodesWithFreeSlots);
}
// requested host is still alive but cannot accept task, pick the next available host in consistent order
for (int i = 0; i < allNodes.size(); i++) {
NodeInfo nodeInfo = allNodes.get((i + requestedHostIdx + 1) % allNodes.size());
// next node in consistent order died or does not have free slots, rollover to next
if (nodeInfo == null || !nodeInfo.canAcceptTask()) {
continue;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Assigning {} in consistent order when looking for first requested host, from #hosts={}," + " requestedHosts={}", nodeInfo.toShortString(), allNodes.size(), ((requestedHosts == null || requestedHosts.length == 0) ? "null" : requestedHostsDebugStr));
}
return new SelectHostResult(nodeInfo);
}
}
return SELECT_HOST_RESULT_DELAYED_RESOURCES;
} finally {
readLock.unlock();
}
}
use of org.apache.hadoop.hive.llap.registry.LlapServiceInstance in project hive by apache.
the class LlapTaskSchedulerService method getAvailableResources.
/**
* The difference between this and getTotalResources() is that this only gives currently free
* resource instances, while the other lists all the instances that may become available in a
* while.
*/
@Override
public Resource getAvailableResources() {
// need a state store eventually for current state & measure backoffs
int memory = 0;
int vcores = 0;
readLock.lock();
try {
int numInstancesFound = 0;
for (LlapServiceInstance inst : activeInstances.getAll()) {
NodeInfo nodeInfo = instanceToNodeMap.get(inst.getWorkerIdentity());
if (nodeInfo != null && !nodeInfo.isDisabled()) {
Resource r = inst.getResource();
memory += r.getMemory();
vcores += r.getVirtualCores();
numInstancesFound++;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("GetAvailableResources: numInstancesFound={}, totalMem={}, totalVcores={}", numInstancesFound, memory, vcores);
}
} finally {
readLock.unlock();
}
return Resource.newInstance(memory, vcores);
}
use of org.apache.hadoop.hive.llap.registry.LlapServiceInstance in project hive by apache.
the class LlapTokenClient method getDelegationToken.
public Token<LlapTokenIdentifier> getDelegationToken(String appId) throws IOException {
if (!UserGroupInformation.isSecurityEnabled())
return null;
Iterator<LlapServiceInstance> llaps = null;
if (clientInstance == null) {
assert client == null;
llaps = getLlapServices(false).iterator();
clientInstance = llaps.next();
}
ByteString tokenBytes = null;
boolean hasRefreshed = false;
while (true) {
try {
tokenBytes = getTokenBytes(appId);
break;
} catch (IOException | ServiceException ex) {
LOG.error("Cannot get a token, trying a different instance", ex);
client = null;
clientInstance = null;
}
if (llaps == null || !llaps.hasNext()) {
if (hasRefreshed) {
// Only refresh once.
throw new RuntimeException("Cannot find any LLAPs to get the token from");
}
llaps = getLlapServices(true).iterator();
hasRefreshed = true;
}
clientInstance = llaps.next();
}
Token<LlapTokenIdentifier> token = extractToken(tokenBytes);
if (LOG.isInfoEnabled()) {
LOG.info("Obtained a LLAP delegation token from " + clientInstance + ": " + token);
}
return token;
}
use of org.apache.hadoop.hive.llap.registry.LlapServiceInstance in project hive by apache.
the class LlapZookeeperRegistryImpl method getAllInstancesOrdered.
// The real implementation for the instanceset... instanceset has its own copy of the
// ZK cache yet completely depends on the parent in every other aspect and is thus unneeded.
Collection<LlapServiceInstance> getAllInstancesOrdered(boolean consistentIndexes, PathChildrenCache instancesCache) {
Map<String, Long> slotByWorker = new HashMap<String, Long>();
Set<LlapServiceInstance> unsorted = Sets.newHashSet();
for (ChildData childData : instancesCache.getCurrentData()) {
if (childData == null)
continue;
byte[] data = childData.getData();
if (data == null)
continue;
String nodeName = extractNodeName(childData);
if (nodeName.startsWith(WORKER_PREFIX)) {
LlapServiceInstance instances = getInstanceByPath(childData.getPath());
if (instances != null) {
unsorted.add(instances);
}
} else if (nodeName.startsWith(SLOT_PREFIX)) {
slotByWorker.put(extractWorkerIdFromSlot(childData), Long.parseLong(nodeName.substring(SLOT_PREFIX.length())));
} else {
LOG.info("Ignoring unknown node {}", childData.getPath());
}
}
TreeMap<Long, LlapServiceInstance> sorted = new TreeMap<>();
long maxSlot = Long.MIN_VALUE;
for (LlapServiceInstance worker : unsorted) {
Long slot = slotByWorker.get(worker.getWorkerIdentity());
if (slot == null) {
LOG.info("Unknown slot for {}", worker.getWorkerIdentity());
continue;
}
maxSlot = Math.max(maxSlot, slot);
sorted.put(slot, worker);
}
if (consistentIndexes) {
// Add dummy instances to all slots where LLAPs are MIA... I can haz insert_iterator?
TreeMap<Long, LlapServiceInstance> dummies = new TreeMap<>();
Iterator<Long> keyIter = sorted.keySet().iterator();
long expected = 0;
Long ts = null;
while (keyIter.hasNext()) {
Long slot = keyIter.next();
assert slot >= expected;
while (slot > expected) {
if (ts == null) {
// Inactive nodes restart every call!
ts = System.nanoTime();
}
dummies.put(expected, new InactiveServiceInstance("inactive-" + expected + "-" + ts));
++expected;
}
++expected;
}
sorted.putAll(dummies);
}
return sorted.values();
}
use of org.apache.hadoop.hive.llap.registry.LlapServiceInstance in project hive by apache.
the class Utils method getSplitLocationProvider.
public static SplitLocationProvider getSplitLocationProvider(Configuration conf, boolean useCacheAffinity, Logger LOG) throws IOException {
boolean useCustomLocations = HiveConf.getVar(conf, HiveConf.ConfVars.HIVE_EXECUTION_MODE).equals("llap") && HiveConf.getBoolVar(conf, HiveConf.ConfVars.LLAP_CLIENT_CONSISTENT_SPLITS) && useCacheAffinity;
SplitLocationProvider splitLocationProvider;
LOG.info("SplitGenerator using llap affinitized locations: " + useCustomLocations);
if (useCustomLocations) {
LlapRegistryService serviceRegistry = LlapRegistryService.getClient(conf);
LOG.info("Using LLAP instance " + serviceRegistry.getApplicationId());
Collection<LlapServiceInstance> serviceInstances = serviceRegistry.getInstances().getAllInstancesOrdered(true);
Preconditions.checkArgument(!serviceInstances.isEmpty(), "No running LLAP daemons! Please check LLAP service status and zookeeper configuration");
ArrayList<String> locations = new ArrayList<>(serviceInstances.size());
for (LlapServiceInstance serviceInstance : serviceInstances) {
if (LOG.isDebugEnabled()) {
LOG.debug("Adding " + serviceInstance.getWorkerIdentity() + " with hostname=" + serviceInstance.getHost() + " to list for split locations");
}
locations.add(serviceInstance.getHost());
}
splitLocationProvider = new HostAffinitySplitLocationProvider(locations);
} else {
splitLocationProvider = new SplitLocationProvider() {
@Override
public String[] getLocations(InputSplit split) throws IOException {
if (split == null) {
return null;
}
String[] locations = split.getLocations();
if (locations != null && locations.length == 1) {
if ("localhost".equals(locations[0])) {
return ArrayUtils.EMPTY_STRING_ARRAY;
}
}
return locations;
}
};
}
return splitLocationProvider;
}
Aggregations