@Override
  public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {

    BizLogSendRequest requestBody = request.getBody();

    List<BizLog> bizLogs = requestBody.getBizLogs();
    if (CollectionUtils.isNotEmpty(bizLogs)) {
      for (BizLog bizLog : bizLogs) {
        JobLogPo jobLogPo = new JobLogPo();
        jobLogPo.setGmtCreated(SystemClock.now());
        jobLogPo.setLogTime(bizLog.getLogTime());
        jobLogPo.setTaskTrackerNodeGroup(bizLog.getTaskTrackerNodeGroup());
        jobLogPo.setTaskTrackerIdentity(bizLog.getTaskTrackerIdentity());
        jobLogPo.setJobId(bizLog.getJobId());
        jobLogPo.setTaskId(bizLog.getTaskId());
        jobLogPo.setMsg(bizLog.getMsg());
        jobLogPo.setSuccess(true);
        jobLogPo.setLevel(bizLog.getLevel());
        jobLogPo.setLogType(LogType.BIZ);
        application.getJobLogger().log(jobLogPo);
      }
    }

    return RemotingCommand.createResponseCommand(
        JobProtos.ResponseCode.BIZ_LOG_SEND_SUCCESS.code(), "");
  }
  /**
   * 发送JobResults
   *
   * @param results
   * @return
   */
  private boolean retrySendJobResults(List<TaskTrackerJobResult> results) {
    // 发送消息给 JobTracker
    TtJobFinishedRequest requestBody =
        application.getCommandBodyWrapper().wrapper(new TtJobFinishedRequest());
    requestBody.setTaskTrackerJobResults(results);
    requestBody.setReSend(true);

    int requestCode = JobProtos.RequestCode.JOB_FINISHED.code();
    RemotingCommand request = RemotingCommand.createRequestCommand(requestCode, requestBody);

    try {
      // 这里一定要用同步,不然异步会发生文件锁,死锁
      RemotingCommand commandResponse = remotingClient.invokeSync(request);
      if (commandResponse != null
          && commandResponse.getCode() == RemotingProtos.ResponseCode.SUCCESS.code()) {
        return true;
      } else {
        LOGGER.warn("Send job failed, {}", commandResponse);
        return false;
      }
    } catch (JobTrackerNotFoundException e) {
      LOGGER.error("Retry send job result failed! jobResults={}", results, e);
    }
    return false;
  }
  @Override
  public RemotingCommand processRequest(ChannelHandlerContext ctx, final RemotingCommand request)
      throws RemotingCommandException {

    JobPushRequest requestBody = request.getBody();

    // JobTracker 分发来的 job
    final JobWrapper jobWrapper = requestBody.getJobWrapper();

    try {
      application.getRunnerPool().execute(jobWrapper, jobRunnerCallback);
    } catch (NoAvailableJobRunnerException e) {
      // 任务推送失败
      return RemotingCommand.createResponseCommand(
          JobProtos.ResponseCode.NO_AVAILABLE_JOB_RUNNER.code(),
          "job push failure , no available job runner!");
    }

    // 任务推送成功
    return RemotingCommand.createResponseCommand(
        JobProtos.ResponseCode.JOB_PUSH_SUCCESS.code(), "job push success!");
  }
    @Override
    public JobWrapper runComplete(Response response) {
      // 发送消息给 JobTracker
      final TaskTrackerJobResult taskTrackerJobResult = new TaskTrackerJobResult();
      taskTrackerJobResult.setTime(SystemClock.now());
      taskTrackerJobResult.setJobWrapper(response.getJobWrapper());
      taskTrackerJobResult.setAction(response.getAction());
      taskTrackerJobResult.setMsg(response.getMsg());
      TtJobFinishedRequest requestBody =
          application.getCommandBodyWrapper().wrapper(new TtJobFinishedRequest());
      requestBody.addJobResult(taskTrackerJobResult);
      requestBody.setReceiveNewJob(response.isReceiveNewJob()); // 设置可以接受新任务

      int requestCode = JobProtos.RequestCode.JOB_FINISHED.code();

      RemotingCommand request = RemotingCommand.createRequestCommand(requestCode, requestBody);

      final Response returnResponse = new Response();

      try {
        final CountDownLatch latch = new CountDownLatch(1);
        remotingClient.invokeAsync(
            request,
            new InvokeCallback() {
              @Override
              public void operationComplete(ResponseFuture responseFuture) {
                try {
                  RemotingCommand commandResponse = responseFuture.getResponseCommand();

                  if (commandResponse != null
                      && commandResponse.getCode() == RemotingProtos.ResponseCode.SUCCESS.code()) {
                    JobPushRequest jobPushRequest = commandResponse.getBody();
                    if (jobPushRequest != null) {
                      LOGGER.info("Get new job :{}", jobPushRequest.getJobWrapper());
                      returnResponse.setJobWrapper(jobPushRequest.getJobWrapper());
                    }
                  } else {
                    LOGGER.info("Job feedback failed, save local files。{}", taskTrackerJobResult);
                    try {
                      retryScheduler.inSchedule(
                          taskTrackerJobResult.getJobWrapper().getJobId().concat("_")
                              + SystemClock.now(),
                          taskTrackerJobResult);
                    } catch (Exception e) {
                      LOGGER.error("Job feedback failed", e);
                    }
                  }
                } finally {
                  latch.countDown();
                }
              }
            });

        try {
          latch.await(Constants.LATCH_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
          throw new RequestTimeoutException(e);
        }
      } catch (JobTrackerNotFoundException e) {
        try {
          LOGGER.warn("No job tracker available! save local files.");
          retryScheduler.inSchedule(
              taskTrackerJobResult.getJobWrapper().getJobId().concat("_") + SystemClock.now(),
              taskTrackerJobResult);
        } catch (Exception e1) {
          LOGGER.error("Save files failed, {}", taskTrackerJobResult.getJobWrapper(), e1);
        }
      }

      return returnResponse.getJobWrapper();
    }