public ScheduleDataManager4ZK(ZKManager aZkManager) throws Exception { this.zkManager = aZkManager; this.gson = new GsonBuilder() .registerTypeAdapter(Timestamp.class, new TimestampTypeAdapter()) .setDateFormat(ScheduleUtil.DATA_FORMAT_YYYYMMDDHHMMSS) .create(); this.pathServer = this.zkManager.getRootPath() + "/" + NODE_SERVER; this.pathTask = this.zkManager.getRootPath() + "/" + NODE_TASK; this.random = new Random(); if (this.getZooKeeper().exists(this.pathServer, false) == null) { ZKTools.createPath( getZooKeeper(), this.pathServer, CreateMode.PERSISTENT, this.zkManager.getAcl()); } loclaBaseTime = System.currentTimeMillis(); String tempPath = this.zkManager .getZooKeeper() .create( this.zkManager.getRootPath() + "/systime", null, this.zkManager.getAcl(), CreateMode.EPHEMERAL_SEQUENTIAL); Stat tempStat = this.zkManager.getZooKeeper().exists(tempPath, false); zkBaseTime = tempStat.getCtime(); ZKTools.deleteTree(getZooKeeper(), tempPath); if (Math.abs(this.zkBaseTime - this.loclaBaseTime) > 5000) { LOG.error( "请注意,Zookeeper服务器时间与本地时间相差 : " + Math.abs(this.zkBaseTime - this.loclaBaseTime) + " ms"); } }
@Override // @wjw_note: 删除此server下的所有zookeeper上的数据! public void UnRegisterScheduleServer(ScheduleServer server) throws Exception { // 1. 删除server String zkPath = this.pathServer; if (this.getZooKeeper().exists(zkPath, false) != null) { ZKTools.deleteTree(this.getZooKeeper(), zkPath + "/" + server.getUuid()); } // 2. 删除task zkPath = this.pathTask; if (this.getZooKeeper().exists(zkPath, false) == null) { return; } List<String> children = this.getZooKeeper().getChildren(zkPath, false); if (null == children || children.size() == 0) { return; } for (int i = 0; i < children.size(); i++) { String taskName = children.get(i); String taskPath = zkPath + "/" + taskName + "/" + server.getUuid(); if (this.getZooKeeper().exists(taskPath, false) != null) { ZKTools.deleteTree(this.getZooKeeper(), taskPath); } } }
// @wjw_note: 把任务分配给taskServerList里随机的一个server! private void assignServer2Task(List<String> taskServerList, String taskPath) throws Exception { // @wjw_note: 清除过期的无Runner的Task { Stat stat = new Stat(); this.getZooKeeper().getData(taskPath, null, stat); if (getSystemTime() - stat.getMtime() > TASK_EXPIRE_TIME) { ZKTools.deleteTree(this.getZooKeeper(), taskPath); LOG.warn("清除过期的无Runner的Task[" + taskPath + "]"); return; } } int index = random.nextInt(taskServerList.size()); String serverId = taskServerList.get(index); this.getZooKeeper() .create(taskPath + "/" + serverId, null, this.zkManager.getAcl(), CreateMode.PERSISTENT); if (LOG.isDebugEnabled()) { StringBuilder buffer = new StringBuilder(); buffer .append("Assign server [") .append(serverId) .append("]") .append(" to task [") .append(taskPath) .append("]"); LOG.debug(buffer.toString()); } }
@Override public void deleteTaskOwner(String taskName, String uuid) throws Exception { String taskOwnerPath = this.pathTask + "/" + taskName + "/" + uuid; if (this.getZooKeeper().exists(taskOwnerPath, false) != null) { ZKTools.deleteTree(this.getZooKeeper(), taskOwnerPath); } }
public void clearExpireScheduleServer() throws Exception { String zkPath = this.pathServer; if (this.getZooKeeper().exists(zkPath, false) == null) { this.getZooKeeper().create(zkPath, null, this.zkManager.getAcl(), CreateMode.PERSISTENT); } for (String name : this.zkManager.getZooKeeper().getChildren(zkPath, false)) { try { Stat stat = new Stat(); this.getZooKeeper().getData(zkPath + "/" + name, null, stat); if (getSystemTime() - stat.getMtime() > SERVER_EXPIRE_TIME) { ZKTools.deleteTree(this.getZooKeeper(), zkPath + "/" + name); LOG.warn("清除过期ScheduleServer[" + zkPath + "/" + name + "]"); } } catch (Exception e) { // 当有多台服务器时,存在并发清理的可能,忽略异常 } } }
@Override // @wjw_note: 非常重要的,分配任务的逻辑! public void assignTask(String currentUuid, List<String> taskServerList) throws Exception { if (this.zkManager.isZookeeperConnected() == false) { return; } if (this.isLeader(currentUuid, taskServerList) == false) { if (LOG.isDebugEnabled()) { LOG.debug(currentUuid + ":不是负责任务分配的Leader,直接返回"); } return; } if (LOG.isDebugEnabled()) { LOG.debug(currentUuid + ":开始重新分配任务......"); } if (taskServerList.size() <= 0) { // 在服务器动态调整的时候,可能出现服务器列表为空的清空 return; } String zkPath = this.pathTask; if (this.getZooKeeper().exists(zkPath, false) == null) { this.getZooKeeper().create(zkPath, null, this.zkManager.getAcl(), CreateMode.PERSISTENT); } List<String> taskChildren = this.getZooKeeper().getChildren(zkPath, false); if (null == taskChildren || taskChildren.size() == 0) { if (LOG.isDebugEnabled()) { LOG.debug(currentUuid + ":没有集群任务"); } return; } for (int i = 0; i < taskChildren.size(); i++) { String taskName = taskChildren.get(i); String taskPath = zkPath + "/" + taskName; if (this.getZooKeeper().exists(taskPath, false) == null) { this.getZooKeeper().create(taskPath, null, this.zkManager.getAcl(), CreateMode.PERSISTENT); } List<String> taskServerIds = this.getZooKeeper().getChildren(taskPath, false); if (null == taskServerIds || taskServerIds.size() == 0) { // 执行task的节点是空的 assignServer2Task(taskServerList, taskPath); } else { boolean hasAssignSuccess = false; for (String serverId : taskServerIds) { if (taskServerList.contains(serverId)) { Stat stat = new Stat(); this.getZooKeeper().getData(taskPath + "/" + serverId, null, stat); if (getSystemTime() - stat.getMtime() < TASK_EXPIRE_TIME) { // @wjw_note: 判断task Owner节点是否过期 hasAssignSuccess = true; continue; } } LOG.warn("删除僵尸Task Runner: " + taskPath + "/" + serverId); ZKTools.deleteTree( this.getZooKeeper(), taskPath + "/" + serverId); // @wjw_note: 删除某一节点已经死掉的残留下来的僵尸task! } if (hasAssignSuccess == false) { assignServer2Task( taskServerList, taskPath); // @wjw_note: 把任务分配给taskServerList里随机的一个server! } } } }