com.vip.saturn.job.console.service.impl.ExecutorServiceImpl Maven / Gradle / Ivy
/**
* Copyright 1999-2015 dangdang.com.
*
* Licensed 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 com.vip.saturn.job.console.service.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.vip.saturn.job.console.domain.*;
import com.vip.saturn.job.console.exception.SaturnJobConsoleException;
import com.vip.saturn.job.console.repository.zookeeper.CuratorRepository;
import com.vip.saturn.job.console.repository.zookeeper.CuratorRepository.CuratorFrameworkOp;
import com.vip.saturn.job.console.service.ExecutorService;
import com.vip.saturn.job.console.service.JobService;
import com.vip.saturn.job.console.service.RegistryCenterService;
import com.vip.saturn.job.console.service.SystemConfigService;
import com.vip.saturn.job.console.service.helper.SystemConfigProperties;
import com.vip.saturn.job.console.utils.ExecutorNodePath;
import com.vip.saturn.job.console.utils.JobNodePath;
import com.vip.saturn.job.console.utils.SaturnConsoleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.io.File;
import java.util.List;
import java.util.Set;
/**
* Default implementation of ExecutorService.
*/
public class ExecutorServiceImpl implements ExecutorService {
private static final int DEFAULT_MAX_SECONDS_FORCE_KILL_EXECUTOR = 300;
private static final int SMALLEST_VERSION_SUPPORTED_DUMP = 3;
private static final Set SUPPORT_DUMP_VERSION_WHITE_LIST = Sets.newHashSet("saturn-dev", "master-SNAPSHOT");
@Resource
private CuratorRepository curatorRepository;
@Resource
private JobService jobService;
@Resource
private RegistryCenterService registryCenterService;
@Resource
private SystemConfigService systemConfigService;
@Override
public List getExecutors(String namespace) throws SaturnJobConsoleException {
return getExecutors(namespace, null);
}
@Override
public List getExecutors(String namespace, ServerStatus expectedServerStatus)
throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
List executors = curatorFrameworkOp.getChildren(ExecutorNodePath.getExecutorNodePath());
if (executors == null || executors.isEmpty()) {
return Lists.newArrayList();
}
List executorInfoList = Lists.newArrayList();
for (String executor : executors) {
ServerBriefInfo executorInfo = getServerBriefInfo(executor, curatorFrameworkOp);
if (expectedServerStatus == null || executorInfo.getStatus() == expectedServerStatus) {
executorInfoList.add(executorInfo);
}
}
return executorInfoList;
}
@Override
public ServerBriefInfo getExecutor(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
if (!curatorFrameworkOp.checkExists(ExecutorNodePath.getExecutorNodePath(executorName))) {
return null;
}
return getServerBriefInfo(executorName, curatorFrameworkOp);
}
private ServerBriefInfo getServerBriefInfo(String executorName, CuratorFrameworkOp curatorFrameworkOp) {
ServerBriefInfo executorInfo = new ServerBriefInfo(executorName);
String ip = curatorFrameworkOp.getData(ExecutorNodePath.getExecutorIpNodePath(executorName));
executorInfo.setServerIp(ip);
if (StringUtils.isNotBlank(ip)) {
executorInfo.setStatus(ServerStatus.ONLINE);
} else {
executorInfo.setStatus(ServerStatus.OFFLINE);
}
String restartNodePath = ExecutorNodePath.getExecutorRestartNodePath(executorName);
long restartTriggerTime = curatorFrameworkOp.getCtime(restartNodePath);
long now = System.currentTimeMillis();
long maxRestartInv = systemConfigService.getIntegerValue(SystemConfigProperties.MAX_SECONDS_FORCE_KILL_EXECUTOR,
DEFAULT_MAX_SECONDS_FORCE_KILL_EXECUTOR) * 1000L;
// 如果restart结点存在,restart结点存在的时间<300s,executor状态列显示RESTARTING;
if (0 != restartTriggerTime && now - restartTriggerTime < maxRestartInv) {
executorInfo.setRestarting(true);
} else {
executorInfo.setRestarting(false);
}
// 是否已被摘流量
executorInfo.setNoTraffic(
curatorFrameworkOp.checkExists(ExecutorNodePath.getExecutorNoTrafficNodePath(executorName)));
// lastBeginTime
String lastBeginTime = curatorFrameworkOp
.getData(ExecutorNodePath.getExecutorNodePath(executorInfo.getExecutorName(), "lastBeginTime"));
executorInfo.setLastBeginTime(SaturnConsoleUtils.parseMillisecond2DisplayTime(lastBeginTime));
// version
executorInfo.setVersion(curatorFrameworkOp.getData(ExecutorNodePath.getExecutorVersionNodePath(executorName)));
String task = curatorFrameworkOp.getData(ExecutorNodePath.getExecutorTaskNodePath(executorName));
if (StringUtils.isNotBlank(task)) {
// 容器组
executorInfo.setGroupName(task);
// 是否容器
executorInfo.setContainer(true);
}
return executorInfo;
}
@Override
public ServerAllocationInfo getExecutorAllocation(String namespace, String executorName)
throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
List unSystemJobs = jobService.getUnSystemJobs(namespace);
ServerAllocationInfo serverAllocationInfo = new ServerAllocationInfo(executorName);
for (JobConfig jobConfig : unSystemJobs) {
String jobName = jobConfig.getJobName();
String serverNodePath = JobNodePath.getServerNodePath(jobName);
if (!curatorFrameworkOp.checkExists(serverNodePath)) {
continue;
}
String sharding = curatorFrameworkOp
.getData(JobNodePath.getServerNodePath(jobName, executorName, "sharding"));
if (StringUtils.isNotBlank(sharding)) {
// 作业状态为STOPPED的即使有残留分片也不显示该分片
if (JobStatus.STOPPED.equals(jobService.getJobStatus(namespace, jobName))) {
continue;
}
// concat executorSharding
serverAllocationInfo.getAllocationMap().put(jobName, sharding);
// calculate totalLoad
String loadLevelNode = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "loadLevel"));
Integer loadLevel = 1;
if (StringUtils.isNotBlank(loadLevelNode)) {
loadLevel = Integer.valueOf(loadLevelNode);
}
int shardingItemNum = sharding.split(",").length;
int curJobLoad = shardingItemNum * loadLevel;
int totalLoad = serverAllocationInfo.getTotalLoadLevel();
serverAllocationInfo.setTotalLoadLevel(totalLoad + curJobLoad);
}
}
return serverAllocationInfo;
}
@Override
public ServerRunningInfo getExecutorRunningInfo(String namespace, String executorName)
throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
List unSystemJobs = jobService.getUnSystemJobs(namespace);
ServerRunningInfo serverRunningInfo = new ServerRunningInfo(executorName);
for (JobConfig jobConfig : unSystemJobs) {
boolean needToCheckFailover = needToCheckFailover(jobConfig);
String jobName = jobConfig.getJobName();
String serverNodePath = JobNodePath.getServerNodePath(jobName);
if (!curatorFrameworkOp.checkExists(serverNodePath)) {
continue;
}
String sharding = curatorFrameworkOp
.getData(JobNodePath.getServerNodePath(jobName, executorName, "sharding"));
Set shardingItems = getShardingItems(sharding);
if (needToCheckFailover) {
obtainServerRunningInfoWhileNeedToCheckFailover(executorName, curatorFrameworkOp, jobName,
shardingItems, serverRunningInfo);
} else if (!shardingItems.isEmpty()) {
obtainServerRunningInfoWhileNoNeedToCheckFailover(curatorFrameworkOp, jobConfig, shardingItems,
serverRunningInfo);
}
}
return serverRunningInfo;
}
private void obtainServerRunningInfoWhileNoNeedToCheckFailover(CuratorFrameworkOp curatorFrameworkOp,
JobConfig jobConfig, Set shardingItems, ServerRunningInfo serverRunningInfo) {
String jobName = jobConfig.getJobName();
// 对于不上报运行状态的作业,所有分配的分片均作为潜在运行中的作业
if (!jobConfig.getEnabledReport()) {
if (jobConfig.getEnabled() != null && jobConfig.getEnabled()) {
serverRunningInfo.getPotentialRunningJobItems().put(jobName, StringUtils.join(shardingItems, ','));
}
return;
}
List runningItems = Lists.newArrayList();
for (String item : shardingItems) {
if (curatorFrameworkOp
.checkExists(JobNodePath.getExecutionNodePath(jobConfig.getJobName(), item, "running"))) {
runningItems.add(item);
}
}
if (!runningItems.isEmpty()) {
serverRunningInfo.getRunningJobItems().put(jobConfig.getJobName(), StringUtils.join(runningItems, ','));
}
}
/**
* 不需要检查潜在运行的作业,因为这类作业不可能failover;
* 遍历所有作业的所有分片,如果存在failover节点,则要看看有没有running节点,如果有running节点则要看看是否自己正在执行failover,如果是加入到runningInfo中,否则continue;
*/
private void obtainServerRunningInfoWhileNeedToCheckFailover(String executorName,
CuratorFrameworkOp curatorFrameworkOp, String jobName, Set shardingItems,
ServerRunningInfo serverRunningInfo) {
List executionItems = curatorFrameworkOp.getChildren(JobNodePath.getExecutionNodePath(jobName));
if (CollectionUtils.isEmpty(executionItems)) {
return;
}
List runningItems = Lists.newArrayList();
for (String item : executionItems) {
boolean isItemRunning = curatorFrameworkOp
.checkExists(JobNodePath.getExecutionNodePath(jobName, item, "running"));
if (!isItemRunning) {
continue;
}
// 属于已经分配的分片
if (shardingItems != null && shardingItems.contains(item)) {
runningItems.add(item);
continue;
}
// 不属于自己分配的分片,则看看是否有failover
String failoverValue = curatorFrameworkOp
.getData(JobNodePath.getExecutionNodePath(jobName, item, "failover"));
if (StringUtils.isNotBlank(failoverValue) && failoverValue.equals(executorName)) {
runningItems.add(item);
}
}
if (!runningItems.isEmpty()) {
serverRunningInfo.getRunningJobItems().put(jobName, StringUtils.join(runningItems, ','));
}
}
private Set getShardingItems(String sharding) {
if (StringUtils.isBlank(sharding)) {
return Sets.newHashSet();
}
String items[] = sharding.split(",");
Set result = Sets.newTreeSet();
for (String item : items) {
if (StringUtils.isBlank(item)) {
continue;
}
result.add(item.trim());
}
return result;
}
private boolean needToCheckFailover(JobConfig jobConfig) {
if (!jobConfig.getFailover()) {
return false;
}
//下面的检查是避免脏数据
if (JobType.isMsg(JobType.getJobType(jobConfig.getJobType()))) {
return false;
}
if (jobConfig.getLocalMode()) {
return false;
}
if (!jobConfig.getEnabledReport()) {
return false;
}
return true;
}
@Override
public void extractTraffic(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
validateIfExecutorNameExisted(executorName, curatorFrameworkOp);
curatorFrameworkOp.create(ExecutorNodePath.getExecutorNoTrafficNodePath(executorName));
}
@Override
public void recoverTraffic(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
validateIfExecutorNameExisted(executorName, curatorFrameworkOp);
curatorFrameworkOp.deleteRecursive(ExecutorNodePath.getExecutorNoTrafficNodePath(executorName));
}
@Override
public void removeExecutor(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
curatorFrameworkOp.deleteRecursive(ExecutorNodePath.getExecutorNodePath(executorName));
List jobNames = jobService.getAllJobNamesFromZK(namespace);
if (CollectionUtils.isEmpty(jobNames)) {
return;
}
for (String jobName : jobNames) {
String executorNode = JobNodePath.getServerNodePath(jobName, executorName);
curatorFrameworkOp.deleteRecursive(executorNode);
}
}
@Override
public void shardAll(String namespace) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
String shardAllAtOnceNodePath = ExecutorNodePath.getExecutorShardingNodePath("shardAllAtOnce");
curatorFrameworkOp.deleteRecursive(shardAllAtOnceNodePath);
curatorFrameworkOp.create(shardAllAtOnceNodePath);
}
@Override
public void dump(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
String version = curatorFrameworkOp.getData(ExecutorNodePath.getExecutorVersionNodePath(executorName));
if (!isVersionSupportedDump(version)) {
throw new SaturnJobConsoleException(SaturnJobConsoleException.ERROR_CODE_BAD_REQUEST,
"Saturn executor版本低于3.0.0无法进行一键dump");
}
String dumpNodePath = ExecutorNodePath.getExecutorDumpNodePath(executorName);
curatorFrameworkOp.delete(dumpNodePath);
curatorFrameworkOp.create(dumpNodePath);
}
private boolean isVersionSupportedDump(String version) {
if (SUPPORT_DUMP_VERSION_WHITE_LIST.contains(version)) {
return true;
}
String[] items = version.split("\\.");
if (items.length < 3) {
return false;
}
int majorVersion = Integer.parseInt(items[0]);
return majorVersion >= SMALLEST_VERSION_SUPPORTED_DUMP;
}
@Override
public File dumpAsFile(String namespace, String executorName) throws SaturnJobConsoleException {
throw new UnsupportedOperationException("this method is not supported yet");
}
@Override
public void restart(String namespace, String executorName) throws SaturnJobConsoleException {
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp = getCuratorFrameworkOp(namespace);
String restartNodePath = ExecutorNodePath.getExecutorRestartNodePath(executorName);
curatorFrameworkOp.delete(restartNodePath);
curatorFrameworkOp.create(restartNodePath);
}
private void validateIfExecutorNameExisted(String executorName,
CuratorRepository.CuratorFrameworkOp curatorFrameworkOp) throws SaturnJobConsoleException {
if (!curatorFrameworkOp.checkExists(ExecutorNodePath.getExecutorNodePath(executorName))) {
throw new SaturnJobConsoleException("The executorName(" + executorName + ") is not existed.");
}
}
protected CuratorFrameworkOp getCuratorFrameworkOp(String namespace) throws SaturnJobConsoleException {
return registryCenterService.getCuratorFrameworkOp(namespace);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy