package com.alibaba.doris.admin.service.common.migrate.command; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.alibaba.doris.admin.dataobject.PhysicalNodeDO; import com.alibaba.doris.admin.monitor.MonitorEnum; import com.alibaba.doris.admin.monitor.SystemLogMonitor; import com.alibaba.doris.admin.service.common.node.NodesManager; import com.alibaba.doris.client.net.Connection; import com.alibaba.doris.client.net.OperationFuture; import com.alibaba.doris.common.MigrateTypeEnum; import com.alibaba.doris.common.MonitorWarnConstants; import com.alibaba.doris.common.migrate.MigrateSubCommand; import com.alibaba.doris.common.route.MigrationRoutePair; import com.alibaba.fastjson.JSON; /** * 迁移命令 * * @author frank */ public class MigrateCommand { private static final Log log = LogFactory.getLog(MigrateCommand.class); private static final String E = "execute"; private static final String F = "finish"; /** * 执行迁移命令 * * @param srourcePhysicalId 迁出节点物理Id * @param targetPhysicalIdList 迁入节点物理Id列表,失效恢复的时候size为1 * @param migerateType 迁移类型 * @return true:发送成功,false:发送失败,null:不需要发送 */ public static MigrateCommandResult executeMigerate(String sourcePhysicalId, List<String> targetPhysicalIdList, MigrateTypeEnum migrateType) { String param = buildParam(sourcePhysicalId, targetPhysicalIdList, migrateType); MigrateCommandResult mcr = new MigrateCommandResult(); mcr.setCommandParam(param); if (param != null) { if (log.isInfoEnabled()) { log.info("send migerate command " + migrateType + " about " + sourcePhysicalId + " -----> " + targetPhysicalIdList); } boolean migReturn = sendMigrateCommand(sourcePhysicalId, migrateType, param, E); mcr.setResult(migReturn); if (!migReturn) { SystemLogMonitor.error(MonitorEnum.MIGRATION, MonitorWarnConstants.FAIL_TO_SEND_MIGRATE_COMMAND + ":" + sourcePhysicalId + " -> " + targetPhysicalIdList); } } else { if (log.isInfoEnabled()) { log.info("NO PRARMETER NEED send migerate command " + migrateType + " about " + sourcePhysicalId + " -----> " + targetPhysicalIdList); } } return mcr; } private static boolean sendMigrateCommand(String sourcePhysicalId, MigrateTypeEnum migrateType, String param, String ef) { try { Connection con = NodesManager.getInstance().getNodeConnection(sourcePhysicalId, false); if (con == null) { return false; } if (log.isDebugEnabled()) { log.debug("The connection got for source node :" + sourcePhysicalId + " is " + con.toString() + ", para =" + param); } OperationFuture<String> future = null; if (MigrateTypeEnum.EXPANSION.equals(migrateType)) { if (E.equals(ef)) { future = con.migrate(MigrateSubCommand.EXPANSION_START.getValue(), param); } if (F.equals(ef)) { future = con.migrate(MigrateSubCommand.EXPANSION_ALL_FINISHED.getValue(), param); } } if (MigrateTypeEnum.TEMP_FAILOVER.equals(migrateType)) { if (E.equals(ef)) { future = con.migrate(MigrateSubCommand.TEMP_FAILOVER_START.getValue(), param); } if (F.equals(ef)) { future = con.migrate(MigrateSubCommand.TEMP_FAILOVER_ALL_FINISHED.getValue(), param); } } if (MigrateTypeEnum.FOREVER_FAILOVER.equals(migrateType)) { if (E.equals(ef)) { future = con.migrate(MigrateSubCommand.FOREVER_FAILOVER_START.getValue(), param); } if (F.equals(ef)) { cleanTempData(param);//clean 临时节点失效期间的数据,临时节点还担负一个使命:更新路由,而且一定要先于对等节点更新(这行代码在下面代码的上面,㤯) future = con.migrate(MigrateSubCommand.FOREVER_FAILOVER_ALL_FINISHED.getValue(), param); } } if (future == null) { return false; } String result; try { result = future.get(3000, TimeUnit.MILLISECONDS); if (log.isInfoEnabled()) { log.info("message from data server after sent migrate command:" + result); } } catch (TimeoutException e) { if (log.isErrorEnabled()) { log.error(e); } return false; } } catch (InterruptedException e) { if (log.isErrorEnabled()) { log.error(e); } return false; } catch (ExecutionException e) { if (log.isErrorEnabled()) { log.error(e); } return false; } catch (Throwable e) { if (log.isErrorEnabled()) { log.error(e); } return false; } return true; } /** * 清除永久失效恢复完成后对应的临时节点的数据 * * @param param * @return */ public static boolean cleanTempData(String param) { boolean result = true; List<PhysicalNodeDO> tempNodeList = NodesManager.getInstance().getAllTempNodeList(); for (PhysicalNodeDO node : tempNodeList) { String nodeId = node.getPhysicalId(); try { Connection con = NodesManager.getInstance().getNodeConnection(nodeId, false); OperationFuture<String> future = con.migrate(MigrateSubCommand.DATACLEAN.getValue(), param); future.get(3000, TimeUnit.MILLISECONDS); } catch (Exception e) { if (log.isErrorEnabled()) { log.error(e); } result = false; SystemLogMonitor.error(MonitorEnum.MIGRATION, MonitorWarnConstants.FAIL_TO_SEND_CLEAN_DATA_COMMAND + ":" + nodeId, e); continue; } } return result; } /** * 迁移结束命令 * * @param sourcePhysicalId * @param targetPhysicalIdList * @param migrateType * @return */ public static boolean finishMigerate(String sourcePhysicalId, List<String> targetPhysicalIdList, String param, MigrateTypeEnum migrateType) { if (param != null) { if (log.isInfoEnabled()) { log.info("send migerate finish command " + migrateType + " about " + sourcePhysicalId + " -----> " + targetPhysicalIdList); } boolean migReturn = sendMigrateCommand(sourcePhysicalId, migrateType, param, F); if (!migReturn) { SystemLogMonitor.error(MonitorEnum.MIGRATION, MonitorWarnConstants.FAIL_TO_SEND_MIGRATE_FINISH_COMMAND + ":" + sourcePhysicalId + " -> " + targetPhysicalIdList); } return migReturn; } if (log.isInfoEnabled()) { log.info("NO PRARMETER NEED send migerate finish command " + migrateType + " about " + sourcePhysicalId + " -----> " + targetPhysicalIdList); } return false; } private static String buildParam(String sourcePhysicalId, List<String> targetPhysicalIdList, MigrateTypeEnum migrateType) { List<MigrationRoutePair> pairList = null; if (migrateType.equals(MigrateTypeEnum.EXPANSION)) { pairList = CommandParser.parseExpansionCommand(sourcePhysicalId, targetPhysicalIdList); } if (migrateType.equals(MigrateTypeEnum.TEMP_FAILOVER) || migrateType.equals(MigrateTypeEnum.FOREVER_FAILOVER)) { pairList = CommandParser.parseFailCommand(sourcePhysicalId, targetPhysicalIdList.get(0)); } if (pairList == null || pairList.isEmpty()) { return null; } String param = JSON.toJSONString(pairList); if (log.isInfoEnabled()) { log.info("command ---" + param); } return param; } public static void main(String[] args) { List<MigrationRoutePair> l = new ArrayList<MigrationRoutePair>(); MigrationRoutePair p = new MigrationRoutePair(); p.setTargetPhysicalId("x"); p.setVnode(2); l.add(p); p = new MigrationRoutePair(); p.setTargetPhysicalId("y"); p.setVnode(4); l.add(p); String s = JSON.toJSONString(l); System.out.println(s); List<MigrationRoutePair> l1 = JSON.parseArray(s, MigrationRoutePair.class); System.out.println(l1); } }