Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public class LlapStatusServiceDriver {
private static final Logger CONSOLE_LOGGER = LoggerFactory.getLogger("LlapStatusServiceDriverConsole");

private static final EnumSet<State> NO_YARN_SERVICE_INFO_STATES = EnumSet.of(
State.APP_NOT_FOUND, State.COMPLETE, State.LAUNCHING);
State.COMPLETE, State.LAUNCHING);
private static final EnumSet<State> LAUNCHING_STATES = EnumSet.of(
State.LAUNCHING, State.RUNNING_PARTIAL, State.RUNNING_ALL);

Expand Down Expand Up @@ -107,6 +107,10 @@ public class LlapStatusServiceDriver {

private static final long LOG_SUMMARY_INTERVAL = 15000L; // Log summary every ~15 seconds.
private static final String LLAP_KEY = "llap";
private static final String TEZ_AM_FRAMEWORK_MODE = "tez.am.framework.mode";
private static final String TEZ_FRAMEWORK_MODE_STANDALONE_ZOOKEEPER = "STANDALONE_ZOOKEEPER";
/** When set, overrides auto-detection for registry vs YARN status lookup. */
private static final String CONFIG_STATUS_USE_REGISTRY = CONF_PREFIX + "status.use-registry";

private final Configuration conf;
private String appName = null;
Expand Down Expand Up @@ -194,18 +198,31 @@ public ExitCode run(LlapStatusServiceCommandLine cl, long watchTimeoutMs) {
llapRegistryConf.set(HiveConf.ConfVars.LLAP_DAEMON_SERVICE_HOSTS.varname, "@" + appName);
}

if (usesRegistryBasedLlapStatus(conf)) {
LOG.info("Non-YARN LLAP deployment detected; using LLAP registry for status");
try {
ExitCode ret = populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs, true);
if (ret == ExitCode.SUCCESS) {
updateRunningThresholdAchieved(appStatusBuilder, cl.getRunningNodesThreshold());
}
return ret;
} catch (LlapStatusCliException e) {
logError(e);
return e.getExitCode();
}
}

try {
if (serviceClient == null) {
serviceClient = LlapSliderUtils.createServiceClient(conf);
}
} catch (Exception e) {
LlapStatusCliException le = new LlapStatusCliException(
ExitCode.SERVICE_CLIENT_ERROR_CREATE_FAILED, "Failed to create service client", e);
LlapStatusCliException le = new LlapStatusCliException(ExitCode.SERVICE_CLIENT_ERROR_CREATE_FAILED,
"Failed to create YARN Service client", e);
logError(le);
return le.getExitCode();
}

// Get the App report from YARN
ApplicationReport appReport;
try {
appReport = getAppReport(appName, cl.getFindAppTimeoutMs());
Expand All @@ -214,7 +231,6 @@ public ExitCode run(LlapStatusServiceCommandLine cl, long watchTimeoutMs) {
return e.getExitCode();
}

// Process the report
ExitCode ret;
try {
ret = processAppReport(appReport, appStatusBuilder);
Expand All @@ -225,30 +241,35 @@ public ExitCode run(LlapStatusServiceCommandLine cl, long watchTimeoutMs) {

if (ret != ExitCode.SUCCESS) {
return ret;
} else if (NO_YARN_SERVICE_INFO_STATES.contains(appStatusBuilder.getState())) {
}

if (NO_YARN_SERVICE_INFO_STATES.contains(appStatusBuilder.getState())) {
updateRunningThresholdAchieved(appStatusBuilder, cl.getRunningNodesThreshold());
return ExitCode.SUCCESS;
} else {
// Get information from YARN Service
try {
ret = populateAppStatusFromServiceStatus(appName, serviceClient, appStatusBuilder);
} catch (LlapStatusCliException e) {
// In case of failure, send back whatever is constructed so far - which would be from the AppReport
logError(e);
return e.getExitCode();
}
}

// Get information from YARN Service
try {
ret = populateAppStatusFromServiceStatus(appName, serviceClient, appStatusBuilder);
} catch (LlapStatusCliException e) {
// In case of failure, send back whatever is constructed so far - which would be from the AppReport
logError(e);
return e.getExitCode();
}

if (ret != ExitCode.SUCCESS) {
return ret;
} else {
try {
ret = populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs);
} catch (LlapStatusCliException e) {
logError(e);
return e.getExitCode();
}
}

try {
ret = populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs, false);
} catch (LlapStatusCliException e) {
logError(e);
return e.getExitCode();
}
if (ret == ExitCode.SUCCESS) {
updateRunningThresholdAchieved(appStatusBuilder, cl.getRunningNodesThreshold());
}
return ret;
} finally {
LOG.debug("Final AppState: " + appStatusBuilder.toString());
Expand Down Expand Up @@ -404,6 +425,11 @@ private ExitCode populateAppStatusFromServiceStatus(String appName, ServiceClien
*/
private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBuilder, long watchTimeoutMs)
throws LlapStatusCliException {
return populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs, false);
}

private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBuilder, long watchTimeoutMs,
boolean registryOnly) throws LlapStatusCliException {

if (llapRegistry == null) {
try {
Expand All @@ -427,6 +453,23 @@ private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBui
appStatusBuilder.setState(State.LAUNCHING);
appStatusBuilder.clearRunningLlapInstances();
return ExitCode.SUCCESS;
}

if (registryOnly) {
List<LlapInstance> registryInstances = new LinkedList<>();
for (LlapServiceInstance serviceInstance : serviceInstances) {
registryInstances.add(createLlapInstanceFromRegistry(serviceInstance));
}
if (appStatusBuilder.getAmInfo() == null) {
appStatusBuilder.setAmInfo(new AmInfo().setAppName(appName));
}
appStatusBuilder.clearAndAddPreviouslyKnownRunningInstances(registryInstances);
appStatusBuilder.setLiveInstances(registryInstances.size());
if (appStatusBuilder.getDesiredInstances() == null) {
appStatusBuilder.setDesiredInstances(registryInstances.size());
}
updateStateFromInstanceCounts(appStatusBuilder, registryInstances.size());
return ExitCode.SUCCESS;
} else {
// Tracks instances known by both YARN Service and llap.
List<LlapInstance> validatedInstances = new LinkedList<>();
Expand Down Expand Up @@ -455,18 +498,10 @@ private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBui

appStatusBuilder.setLiveInstances(validatedInstances.size());
appStatusBuilder.setLaunchingInstances(llapExtraInstances.size());
if (appStatusBuilder.getDesiredInstances() != null &&
validatedInstances.size() >= appStatusBuilder.getDesiredInstances()) {
appStatusBuilder.setState(State.RUNNING_ALL);
if (validatedInstances.size() > appStatusBuilder.getDesiredInstances()) {
LOG.warn("Found more entries in LLAP registry, as compared to desired entries");
}
} else {
if (validatedInstances.size() > 0) {
appStatusBuilder.setState(State.RUNNING_PARTIAL);
} else {
appStatusBuilder.setState(State.LAUNCHING);
}
updateStateFromInstanceCounts(appStatusBuilder, validatedInstances.size());
if (appStatusBuilder.getDesiredInstances() != null
&& validatedInstances.size() > appStatusBuilder.getDesiredInstances()) {
LOG.warn("Found more entries in LLAP registry, as compared to desired entries");
}

// At this point, everything that can be consumed from AppStatusBuilder has been consumed.
Expand All @@ -487,6 +522,63 @@ private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBui
return ExitCode.SUCCESS;
}

static LlapInstance createLlapInstanceFromRegistry(LlapServiceInstance serviceInstance) {
String containerId = serviceInstance.getProperties().get(
HiveConf.ConfVars.LLAP_DAEMON_CONTAINER_ID.varname);
if (StringUtils.isBlank(containerId)) {
containerId = serviceInstance.getWorkerIdentity();
}
LlapInstance llapInstance = new LlapInstance(serviceInstance.getHost(), containerId);
llapInstance.setMgmtPort(serviceInstance.getManagementPort());
llapInstance.setRpcPort(serviceInstance.getRpcPort());
llapInstance.setShufflePort(serviceInstance.getShufflePort());
llapInstance.setWebUrl(serviceInstance.getServicesAddress());
llapInstance.setStatusUrl(serviceInstance.getServicesAddress() + "/status");
return llapInstance;
}

static void updateStateFromInstanceCounts(AppStatusBuilder appStatusBuilder, int liveInstances) {
Integer desiredInstances = appStatusBuilder.getDesiredInstances();
if (desiredInstances != null && liveInstances >= desiredInstances) {
appStatusBuilder.setState(State.RUNNING_ALL);
} else if (liveInstances > 0) {
appStatusBuilder.setState(State.RUNNING_PARTIAL);
} else {
appStatusBuilder.setState(State.LAUNCHING);
}
}

/**
* Non-YARN LLAP (e.g. Kubernetes, standalone Tez) uses the ZK registry for daemon discovery.
* YARN Service LLAP uses the YARN APIs. Detection follows deployment config set by the operator.
*/
static boolean usesRegistryBasedLlapStatus(Configuration conf) {
if (conf.get(CONFIG_STATUS_USE_REGISTRY) != null) {
return conf.getBoolean(CONFIG_STATUS_USE_REGISTRY, false);
}
if (HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_SERVER2_TEZ_USE_EXTERNAL_SESSIONS)) {
return true;
}
String tezFrameworkMode = conf.get(TEZ_AM_FRAMEWORK_MODE, "");
return TEZ_FRAMEWORK_MODE_STANDALONE_ZOOKEEPER.equalsIgnoreCase(tezFrameworkMode);
}

static void updateRunningThresholdAchieved(AppStatusBuilder appStatusBuilder, float runningNodesThreshold) {
Integer desiredInstances = appStatusBuilder.getDesiredInstances();
Integer liveInstances = appStatusBuilder.getLiveInstances();
if (desiredInstances == null || desiredInstances <= 0 || liveInstances == null) {
return;
}
if (!(appStatusBuilder.getState() == State.RUNNING_PARTIAL
|| appStatusBuilder.getState() == State.RUNNING_ALL)) {
return;
}
float ratio = (float) liveInstances / (float) desiredInstances;
if (ratio >= runningNodesThreshold) {
appStatusBuilder.setRunningThresholdAchieved(true);
}
}

private void close() {
if (serviceClient != null) {
serviceClient.stop();
Expand Down
Loading
Loading