hadoop 2.6.0 JvmPauseMonitor源代码分析

JvmPauseMonitor,此类建立一个简单的线程。在此线程中,在循环中运行sleep一段时间方法,如果sleep花费的时间比传递给sleep方法的时间长,就意味着JVM或者宿主机已经出现了停顿处理现象,可能会导致其它问题,如果这种停顿被监测出来,线程会打印一个消息。

/**
 * Class which sets up a simple thread which runs in a loop sleeping
 * for a short interval of time. If the sleep takes significantly longer
 * than its target time, it implies that the JVM or host machine has
 * paused processing, which may cause other problems. If such a pause is
 * detected, the thread logs a message.
 */

下面解析一下JvmPauseMonitor用到的变量和常量:

private static final Log LOG = LogFactory.getLog(
      JvmPauseMonitor.class);

  /** The target sleep time */
  private static final long SLEEP_INTERVAL_MS = 500;//sleep的时间
  
  /** log WARN if we detect a pause longer than this threshold */
  private final long warnThresholdMs; //成员变量,警告时间,如果超时到此时间,则发出警告。
  private static final String WARN_THRESHOLD_KEY =      "jvm.pause.warn-threshold.ms"; // 设置警告时间的配置项
  private static final long WARN_THRESHOLD_DEFAULT = 10000; //静态变量,默认警告时间,如果超时到此时间,则发出警告。
  
  /** log INFO if we detect a pause longer than this threshold */
  private final long infoThresholdMs; //打印提示时间
  private static final String INFO_THRESHOLD_KEY =      "jvm.pause.info-threshold.ms"; //设置提示时间的配置项
  private static final long INFO_THRESHOLD_DEFAULT = 1000; //静态变量,默认提示时间,如果超时到此时间,则发出提示。

  private long numGcWarnThresholdExceeded = 0; //超过告警阈值的次数
  private long numGcInfoThresholdExceeded = 0; //超过提示阈值的次数
  private long totalGcExtraSleepTime = 0;//总的GC导致的另外花费时间
   
  private Thread monitorThread;//监控线程,就是在此线程中循环调用sleep,并且计算时间的。
  private volatile boolean shouldRun = true;//是否应该运行。

以下为静态内部类GcTimes,这个类有gc次数和gc 时间的变量,及其相关实用方法,如subtract,可以提供差值。

private static class GcTimes {
    private GcTimes(GarbageCollectorMXBean gcBean) {
      gcCount = gcBean.getCollectionCount();
      gcTimeMillis = gcBean.getCollectionTime();
    }
    
    private GcTimes(long count, long time) {
      this.gcCount = count;
      this.gcTimeMillis = time;
    }

    private GcTimes subtract(GcTimes other) {
      return new GcTimes(this.gcCount - other.gcCount,
          this.gcTimeMillis - other.gcTimeMillis);
    }
    
    @Override
    public String toString() {
      return "count=" + gcCount + " time=" + gcTimeMillis + "ms";
    }
    
    private long gcCount;
    private long gcTimeMillis;
  }

Monitor线程如下:

private class Monitor implements Runnable {
    @Override
    public void run() {
      Stopwatch sw = new Stopwatch();
      Map<String, GcTimes> gcTimesBeforeSleep = getGcTimes();
      while (shouldRun) {
        sw.reset().start();
        try {
          Thread.sleep(SLEEP_INTERVAL_MS);
        } catch (InterruptedException ie) {
          return;
        }
        long extraSleepTime = sw.elapsedMillis() - SLEEP_INTERVAL_MS;
        Map<String, GcTimes> gcTimesAfterSleep = getGcTimes();

        if (extraSleepTime > warnThresholdMs) {
          ++numGcWarnThresholdExceeded;
          LOG.warn(formatMessage(
              extraSleepTime, gcTimesAfterSleep, gcTimesBeforeSleep));
        } else if (extraSleepTime > infoThresholdMs) {
          ++numGcInfoThresholdExceeded;
          LOG.info(formatMessage(
              extraSleepTime, gcTimesAfterSleep, gcTimesBeforeSleep));
        }
        totalGcExtraSleepTime += extraSleepTime;
        gcTimesBeforeSleep = gcTimesAfterSleep;
      }
    }
  }

Stopwatch用来计时用的, 调用sw.reset().start();来开启新的计时,调用sw.elapsedMillis()返回从开始到现在所用的时间。



你可能感兴趣的:(hadoop 2.6.0 JvmPauseMonitor源代码分析)