/** * Copyright 2016 vip.com. * <p> * 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. * </p> */ package com.vip.saturn.job.console.service.impl; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import com.vip.saturn.job.console.exception.SaturnJobConsoleException; import com.vip.saturn.job.console.repository.zookeeper.CuratorRepository; import com.vip.saturn.job.console.service.RegistryCenterService; import com.vip.saturn.job.console.service.impl.helper.ReuseCallBack; import com.vip.saturn.job.console.service.impl.helper.ReuseUtils; import com.vip.saturn.job.console.utils.SaturnConstants; import org.apache.curator.framework.CuratorFramework; import org.apache.zookeeper.KeeperException.NoNodeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import com.google.common.base.Strings; import com.vip.saturn.job.console.domain.RegistryCenterClient; import com.vip.saturn.job.console.domain.RegistryCenterConfiguration; import com.vip.saturn.job.console.domain.SaturnJunkData; import com.vip.saturn.job.console.domain.SaturnJunkDataOpType; import com.vip.saturn.job.console.exception.JobConsoleException; import com.vip.saturn.job.console.service.SaturnJunkDataService; import com.vip.saturn.job.console.utils.ExecutorNodePath; import com.vip.saturn.job.console.utils.JobNodePath; import com.vip.saturn.job.sharding.node.SaturnExecutorsNode; import javax.annotation.Resource; /** * @author yangjuanying */ @Service public class SaturnJunkDataServiceImpl implements SaturnJunkDataService { protected static Logger log = LoggerFactory.getLogger(SaturnJunkDataServiceImpl.class); @Resource private RegistryCenterService registryCenterService; @Resource private CuratorRepository curatorRepository; @Override public Collection<SaturnJunkData> getJunkData(String zkAddr) { ArrayList<RegistryCenterConfiguration> registryCenterList = RegistryCenterServiceImpl.ZKADDR_TO_ZKCLUSTER_MAP.get(zkAddr).getRegCenterConfList(); if(CollectionUtils.isEmpty(registryCenterList)){ return Collections.emptyList(); } List<SaturnJunkData> saturnJunkDataList = new ArrayList<SaturnJunkData>(); for(RegistryCenterConfiguration registryCenter : registryCenterList){ try { String namespace = registryCenter.getNameAndNamespace(); RegistryCenterClient registryCenterClient = RegistryCenterServiceImpl.getCuratorByNameAndNamespace(namespace); if(registryCenterClient == null){ continue; } String zkBootstrapKey = registryCenter.getBootstrapKey(); CuratorFramework curatorFramework = registryCenterClient.getCuratorClient(); List<String> jobNames = curatorFramework.getChildren().forPath(JobNodePath.get$JobsNodePath()); for (String jobName : jobNames) { if(null != curatorFramework.checkExists().forPath(JobNodePath.getConfigNodePath(jobName))) {// $Jobs/jobName/config exists String toDeletePath = JobNodePath.getConfigNodePath(jobName, "toDelete"); if(null != curatorFramework.checkExists().forPath(toDeletePath)){// toDelete node is junk data SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setPath(toDeletePath); saturnJunkData.setNamespace(namespace); saturnJunkData.setType(SaturnJunkDataOpType.DELETE.toString()); saturnJunkData.setDescription("删除toDelete节点"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } String jobConfigForceShardNodePath = SaturnExecutorsNode.getJobConfigForceShardNodePath(jobName); if (null != curatorFramework.checkExists().forPath(jobConfigForceShardNodePath)) {// forceShard node is junk data SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setPath(jobConfigForceShardNodePath); saturnJunkData.setNamespace(namespace); saturnJunkData.setType(SaturnJunkDataOpType.DELETE.toString()); saturnJunkData.setDescription("删除forceShard节点"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } if(null == curatorFramework.checkExists().forPath(JobNodePath.getServerNodePath(jobName))){ continue; } List<String> jobExecutors = curatorFramework.getChildren().forPath(JobNodePath.getServerNodePath(jobName)); if(CollectionUtils.isEmpty(jobExecutors)){ continue; } for(String jobExecutor : jobExecutors){ String runOneTimePath = JobNodePath.getRunOneTimePath(jobName, jobExecutor); if(null != curatorFramework.checkExists().forPath(runOneTimePath)){// runOneTime node is junk data SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setPath(runOneTimePath); saturnJunkData.setNamespace(namespace); saturnJunkData.setType(SaturnJunkDataOpType.DELETE.toString()); saturnJunkData.setDescription("删除runOneTime节点"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } String stopOneTimePath = JobNodePath.getStopOneTimePath(jobName, jobExecutor); if(null != curatorFramework.checkExists().forPath(stopOneTimePath)){// stopOneTime node is junk data SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setPath(stopOneTimePath); saturnJunkData.setNamespace(namespace); saturnJunkData.setType(SaturnJunkDataOpType.DELETE.toString()); saturnJunkData.setDescription("删除stopOneTime节点"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } String shardingPath = JobNodePath.getServerSharding(jobName,jobExecutor); // $Jobs/servers/executors/executorName/sharding has contents, but this executor is offline,this contents is junk data if(!Strings.isNullOrEmpty(getData(curatorFramework,shardingPath)) && null == curatorFramework.checkExists().forPath(ExecutorNodePath.getExecutorIpNodePath(jobExecutor))){ SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setPath(shardingPath); saturnJunkData.setNamespace(namespace); saturnJunkData.setType(SaturnJunkDataOpType.CLEAR.toString()); saturnJunkData.setDescription("清除sharding内容(原因:该executor不在线)"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } } }else if(!CollectionUtils.isEmpty(curatorFramework.getChildren().forPath(JobNodePath.getJobNodePath(jobName)))) { // if $Jobs/jobName/config is not exists, but $Jobs/jobName/xxx exists,then $Jobs/jobName is junk data SaturnJunkData saturnJunkData = new SaturnJunkData(); saturnJunkData.setType(SaturnJunkDataOpType.DELETE.toString()); saturnJunkData.setPath(JobNodePath.getJobNodePath(jobName)); saturnJunkData.setNamespace(namespace); saturnJunkData.setDescription("删除整个作业节点(原因:$Jobs/"+jobName+"/config节点不存在)"); saturnJunkData.setZkAddr(zkBootstrapKey); saturnJunkDataList.add(saturnJunkData); } } }catch(Exception e){ log.error("getJunkData exception:",e); } } return saturnJunkDataList; } public String getData(final CuratorFramework curatorClient, final String znode) { try { if (null != curatorClient.checkExists().forPath(znode)) { byte[] getZnodeData = curatorClient.getData().forPath(znode); if (getZnodeData == null) {// executor的分片可能存在全部飘走的情况,sharding节点有可能获取到的是null,需要对null做判断,否则new // String时会报空指针异常 return null; } return new String(getZnodeData, Charset.forName("UTF-8")); } else { return null; } } catch (final NoNodeException ex) { return null; // CHECKSTYLE:OFF } catch (final Exception ex) { // CHECKSTYLE:ON throw new JobConsoleException(ex); } } @Override public String removeSaturnJunkData(SaturnJunkData saturnJunkData) { try{ ArrayList<RegistryCenterConfiguration> registryCenterList = RegistryCenterServiceImpl.ZKADDR_TO_ZKCLUSTER_MAP.get(saturnJunkData.getZkAddr()).getRegCenterConfList(); if(CollectionUtils.isEmpty(registryCenterList)){ return "清理废弃数据失败,根据集群zk key:"+saturnJunkData.getZkAddr()+",在注册中心没有取到相关信息"; } for(RegistryCenterConfiguration registryCenter : registryCenterList){ String namespace = registryCenter.getNameAndNamespace(); RegistryCenterClient registryCenterClient = RegistryCenterServiceImpl.getCuratorByNameAndNamespace(namespace); if(registryCenterClient == null){ continue; } CuratorFramework curatorFramework = registryCenterClient.getCuratorClient(); if(SaturnJunkDataOpType.CLEAR.toString().equals(saturnJunkData.getType())){ if(null != curatorFramework.checkExists().forPath(saturnJunkData.getPath())){ curatorFramework.inTransaction().check().forPath(saturnJunkData.getPath()).and().setData().forPath(saturnJunkData.getPath(), "".getBytes(Charset.forName("UTF-8"))).and().commit(); } }else if(SaturnJunkDataOpType.DELETE.toString().equals(saturnJunkData.getType())){ if(null != curatorFramework.checkExists().forPath(saturnJunkData.getPath())){ curatorFramework.delete().deletingChildrenIfNeeded().forPath(saturnJunkData.getPath()); } } } return SaturnConstants.DEAL_SUCCESS; }catch(Exception e){ log.error("removeSaturnJunkData exception:",e); return "清理废弃数据失败:"+e.getMessage(); } } @Override public void deleteRunningNode(String namespace, final String jobName, final Integer item) throws SaturnJobConsoleException { ReuseUtils.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBack<Void>() { @Override public Void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp) throws SaturnJobConsoleException { try { String runningPath = JobNodePath.getExecutionNodePath(jobName, String.valueOf(item), "running"); if(!curatorFrameworkOp.checkExists(runningPath)) { throw new SaturnJobConsoleException("The running path is not existing"); } curatorFrameworkOp.deleteRecursive(runningPath); } catch (SaturnJobConsoleException e) { throw e; } catch (Throwable t) { log.error(t.getMessage(), t); throw new SaturnJobConsoleException(t); } return null; } }); } }