/**
   * failover for trigger remote address
   *
   * @param addressArr
   * @return
   */
  public RemoteCallBack failoverTrigger(
      String handler_address, HashMap<String, String> handler_params, XxlJobLog jobLog) {
    if (handler_address.split(",").length > 1) {

      // for ha
      List<String> addressList = Arrays.asList(handler_address.split(","));
      Collections.shuffle(addressList);

      // for failover
      String failoverMessage = "";
      for (String address : addressList) {
        if (StringUtils.isNotBlank(address)) {
          HashMap<String, String> params = new HashMap<String, String>();
          params.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
          params.put(HandlerParamEnum.ACTION.name(), ActionEnum.BEAT.name());
          RemoteCallBack beatResult = HttpUtil.post(HttpUtil.addressToUrl(address), params);
          failoverMessage +=
              MessageFormat.format(
                  "BEAT running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>",
                  address, beatResult.getStatus(), beatResult.getMsg());
          if (RemoteCallBack.SUCCESS.equals(beatResult.getStatus())) {
            jobLog.setExecutorAddress(address);
            RemoteCallBack triggerCallback =
                HttpUtil.post(HttpUtil.addressToUrl(address), handler_params);
            triggerCallback.setStatus(RemoteCallBack.SUCCESS);
            failoverMessage +=
                MessageFormat.format(
                    "Trigger running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>",
                    address, triggerCallback.getStatus(), triggerCallback.getMsg());
            triggerCallback.setMsg(failoverMessage);
            return triggerCallback;
          }
        }
      }

      RemoteCallBack result = new RemoteCallBack();
      result.setStatus(RemoteCallBack.FAIL);
      result.setMsg(failoverMessage);
      return result;
    } else {
      jobLog.setExecutorAddress(handler_address);
      RemoteCallBack triggerCallback =
          HttpUtil.post(HttpUtil.addressToUrl(handler_address), handler_params);
      String failoverMessage =
          MessageFormat.format(
              "Trigger running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>",
              handler_address, triggerCallback.getStatus(), triggerCallback.getMsg());
      triggerCallback.setMsg(failoverMessage);
      return triggerCallback;
    }
  }
  @Override
  protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    JobKey jobKey = context.getTrigger().getJobKey();

    XxlJobInfo jobInfo =
        DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName());
    // save log
    XxlJobLog jobLog = new XxlJobLog();
    jobLog.setJobGroup(jobInfo.getJobGroup());
    jobLog.setJobName(jobInfo.getJobName());
    jobLog.setJobCron(jobInfo.getJobCron());
    jobLog.setJobDesc(jobInfo.getJobDesc());
    jobLog.setJobClass(jobInfo.getJobClass());
    DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
    logger.info(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());

    // trigger request
    HashMap<String, String> params = new HashMap<String, String>();
    params.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
    params.put(HandlerParamEnum.ACTION.name(), ActionEnum.RUN.name());

    params.put(
        HandlerParamEnum.LOG_ADDRESS.name(), XxlJobLogCallbackServer.getTrigger_log_address());
    params.put(HandlerParamEnum.LOG_ID.name(), String.valueOf(jobLog.getId()));

    params.put(HandlerParamEnum.EXECUTOR_HANDLER.name(), jobInfo.getExecutorHandler());
    params.put(HandlerParamEnum.EXECUTOR_PARAMS.name(), jobInfo.getExecutorParam());

    params.put(HandlerParamEnum.GLUE_SWITCH.name(), String.valueOf(jobInfo.getGlueSwitch()));
    params.put(HandlerParamEnum.JOB_GROUP.name(), jobInfo.getJobGroup());
    params.put(HandlerParamEnum.JOB_NAME.name(), jobInfo.getJobName());

    // failover trigger
    RemoteCallBack callback = failoverTrigger(jobInfo.getExecutorAddress(), params, jobLog);
    jobLog.setExecutorHandler(
        jobInfo.getGlueSwitch() == 0 ? jobInfo.getExecutorHandler() : "GLUE任务");
    jobLog.setExecutorParam(jobInfo.getExecutorParam());
    logger.info(
        ">>>>>>>>>>> xxl-job failoverTrigger response, jobId:{}, callback:{}",
        jobLog.getId(),
        callback);

    // update trigger info
    jobLog.setTriggerTime(new Date());
    jobLog.setTriggerStatus(callback.getStatus());
    jobLog.setTriggerMsg(callback.getMsg());
    DynamicSchedulerUtil.xxlJobLogDao.updateTriggerInfo(jobLog);

    // monitor triger
    JobMonitorHelper.monitor(jobLog.getId());

    logger.info(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
  }