阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Hadoop1.2.1源码解析系列:JT与TT之间的心跳通信机制——TT篇

397次阅读
没有评论

共计 16110 个字符,预计需要花费 41 分钟才能阅读完成。

在 Hadoop 中 JT(JobTracker)与 TT(TaskTracker)之间的通信是通过心跳机制完成的。JT 实现 InterTrackerProtocol 协议,该协议定义了 JT 与 TT 之间的通信机制——心跳。心跳机制实际上就是一个 RPC 请求,JT 作为 Server,而 TT 作为 Client,TT 通过 RPC 调用 JT 的 heartbeat 方法,将 TT 自身的一些状态信息发送给 JT,同时 JT 通过返回值返回对 TT 的指令。

目录

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——TT 篇 http://www.linuxidc.com/Linux/2014-06/103216.htm

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——JT 篇 http://www.linuxidc.com/Linux/2014-06/103217.htm

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——命令篇 http://www.linuxidc.com/Linux/2014-06/103218.htm

心跳有三个作用:

1)判断 TT 是否活着

2)报告 TT 的资源情况以及任务运行情况

3)为 TT 发送指令(如运行 task,kill task 等)

下面详细阅读下涉及到心跳调用的源码。

首先我们需要清楚,心跳机制是 TT 调用 JT 的方法,而非 JT 主动调用 TT 的方法。TT 通过 transmitHeartBeat 方法调用 JT 的 heartbeat 方法。

1.TaskTracker.transmitHeartBeat:

// Send Counters in the status once every COUNTER_UPDATE_INTERVAL
    boolean sendCounters;
    if (now > (previousUpdate + COUNTER_UPDATE_INTERVAL)) {
      sendCounters = true;
      previousUpdate = now;
    }
    else {
      sendCounters = false;
    }

根据 sendCounters 的间隔判断此次心跳是否发送计算器信息。
 
2.TaskTracker.transmitHeartBeat:

1.TaskTracker.transmitHeartBeat:

// Check if the last heartbeat got through…
    // if so then build the heartbeat information for the JobTracker;
    // else resend the previous status information.
    //
    if (status == null) {
      synchronized (this) {
        status = new TaskTrackerStatus(taskTrackerName, localHostname,
                                      httpPort,
                                      cloneAndResetRunningTaskStatuses(
                                        sendCounters),
                                      taskFailures,
                                      localStorage.numFailures(),
                                      maxMapSlots,
                                      maxReduceSlots);
      }
    } else {
      LOG.info(“Resending ‘status’ to ‘” + jobTrackAddr.getHostName() +
              “‘ with reponseId ‘” + heartbeatResponseId);
    }

此处根据 status 变量是否为 null,判断上次的心跳是否成功发送。tatus!=null,则表示上次的心跳尚未发送,所以直接将上次收集到的 TT 状态信息(封装在 status 中)发送给 JT;相反,status==null,则表示上次心跳已完成,重新收集 TT 的状态信息,同样封装到 status 中。下面详细看下 new TaskTrackerStatus()方法。注意此处有个 cloneAndResetRunningTaskStatuses(sendCounters) 方法:

private synchronized List<TaskStatus> cloneAndResetRunningTaskStatuses(
                                          boolean sendCounters) {
    List<TaskStatus> result = new ArrayList<TaskStatus>(runningTasks.size());
    for(TaskInProgress tip: runningTasks.values()) {
      TaskStatus status = tip.getStatus();
      status.setIncludeCounters(sendCounters);
      // send counters for finished or failed tasks and commit pending tasks
      if (status.getRunState() != TaskStatus.State.RUNNING) {
        status.setIncludeCounters(true);
      }
      result.add((TaskStatus)status.clone());
      status.clearStatus();
    }
    return result;
  }

该方法中涉及到 runningTasks 队列,该队列保存了该 TT 上接收的所有未完成的 Task 任务,通过 runningTasks.values() 可以获取 TT 当前所有未完成的 Task,然后获取每个 TaskInProgress 的 status 信息,同时根据第一步判断出的 sendCounters(true/false)决定是否发送 counters 信息(includeCounters),即是否将 counters 对象序列化到 TaskStatus 对象中,这里需要注意如果 TaskInProgress 不处于 Running 状态,则 includeCounters 设为 true,即发送 counters 信息。

————————————– 分割线 ————————————–

Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm

Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm

Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm

Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm

单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm

Hadoop LZO 安装教程 http://www.linuxidc.com/Linux/2013-01/78397.htm

Hadoop 集群上使用 Lzo 压缩 http://www.linuxidc.com/Linux/2012-05/60554.htm

————————————– 分割线 ————————————–

3.TaskTrackerStatus():

public TaskTrackerStatus(String trackerName, String host,
                          int httpPort, List<TaskStatus> taskReports,
                          int taskFailures, int dirFailures,
                          int maxMapTasks, int maxReduceTasks) {
    this.trackerName = trackerName;
    this.host = host;
    this.httpPort = httpPort;

    this.taskReports = new ArrayList<TaskStatus>(taskReports);
    this.taskFailures = taskFailures;
    this.dirFailures = dirFailures;
    this.maxMapTasks = maxMapTasks;
    this.maxReduceTasks = maxReduceTasks;
    this.resStatus = new ResourceStatus();
    this.healthStatus = new TaskTrackerHealthStatus();
  }

这里只是进行简单的变量复制操作,分析下其中一些参数的含义:

1)taskReports:包含该 TT 上目前所有的 Task 状态信息,其中的 counters 信息会根据之前判断 sendCounters 值进行决定是否发送,上一步有提到。

2)taskFailures:该 TT 上失败的 Task 总数(重启会清空),该参数帮助 JT 决定是否向该 TT 提交 Task,因为失败数越多表明该 TT 可能出现 Task 失败的概率越大。

3)dirFailures:这个值是 mapred.local.dir 参数设置的目录中有多少是不可用的(以后会详细提到)

4)maxMapSlots/maxReduceSlots:这个值是 TT 可使用的最大 map 和 reduce slot 数量

初始化完成,继续回到 TaskTracker.transmitHeartBeat 方法。

4.TaskTracker.transmitHeartBeat:

 // Check if we should ask for a new Task
    //
    boolean askForNewTask;
    long localMinSpaceStart;
    synchronized (this) {
      askForNewTask =
        ((status.countOccupiedMapSlots() < maxMapSlots ||
          status.countOccupiedReduceSlots() < maxReduceSlots) &&
        acceptNewTasks);
      localMinSpaceStart = minSpaceStart;
    }
    if (askForNewTask) {
      askForNewTask = enoughFreeSpace(localMinSpaceStart);
      long freeDiskSpace = getFreeSpace();
      long totVmem = getTotalVirtualMemoryOnTT();
      long totPmem = getTotalPhysicalMemoryOnTT();
      long availableVmem = getAvailableVirtualMemoryOnTT();
      long availablePmem = getAvailablePhysicalMemoryOnTT();
      long cumuCpuTime = getCumulativeCpuTimeOnTT();
      long cpuFreq = getCpuFrequencyOnTT();
      int numCpu = getNumProcessorsOnTT();
      float cpuUsage = getCpuUsageOnTT();

      status.getResourceStatus().setAvailableSpace(freeDiskSpace);
      status.getResourceStatus().setTotalVirtualMemory(totVmem);
      status.getResourceStatus().setTotalPhysicalMemory(totPmem);
      status.getResourceStatus().setMapSlotMemorySizeOnTT(
          mapSlotMemorySizeOnTT);
      status.getResourceStatus().setReduceSlotMemorySizeOnTT(
          reduceSlotSizeMemoryOnTT);
      status.getResourceStatus().setAvailableVirtualMemory(availableVmem);
      status.getResourceStatus().setAvailablePhysicalMemory(availablePmem);
      status.getResourceStatus().setCumulativeCpuTime(cumuCpuTime);
      status.getResourceStatus().setCpuFrequency(cpuFreq);
      status.getResourceStatus().setNumProcessors(numCpu);
      status.getResourceStatus().setCpuUsage(cpuUsage);
    }

从源码中的注释可以知道,此处是 TT 根据自身资源使用情况判断是否接收 new task。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-06/103216p2.htm

首先第一步 status.countOccupiedMapSlots() 获得该 TT 上已占用的 map slot 数量:

/**
* Get the number of occupied map slots.
* @return the number of occupied map slots
*/
public int countOccupiedMapSlots() {
int mapSlotsCount = 0;
for (TaskStatus ts : taskReports) {
if (ts.getIsMap() && isTaskRunning(ts)) {
mapSlotsCount += ts.getNumSlots();
}
}
return mapSlotsCount;
}

方法内部是根据 taskReports 中的 TaskStatus 进行判断,这里计算的是 map slot,所以会判断 ts.getIsMap(),如果该 task 是 map 任务,且 isTaskRunning() 返回 true,则获取该 task 所需的 slot 数量。isTaskRunning() 方法内部判断逻辑是:该 task 处于 RUNNING 或者 UNASSIGNED 状态,或者处于 CleanerUp 阶段(这里可能是 Task 处于 FAILED_UNCLEAN 或者 KILLED_UNCLEAN 阶段)。这个方法会计算出 TT 当前已占用的 map slot 数量。同样的通过 countOccupiedReduceSlots() 方法计算出 TT 当前已占用的 reduce slot 数量。获取到 occupied map/reduce slots 后将其同 maxMapSlots/maxReduceSlots 进行比较,这里是“||”而非“&&”,表示只要有 map slot 或者有 reduce slot 就可以接收新任务,当然还需要满足 acceptNewTasks==true 的条件。acceptNewTasks 会在其他地方根据 TT 可使用的空间进行合适的赋值。以上可以判断出是否可以接收新任务,即 askForNewTask 值。

localMinSpaceStart = minSpaceStart,minSpaceStart 由 mapred.local.dir.minspacestart 参数决定,默认是 0,即无限制,该值的意思应该是可接收新任务的 localDirs 最小的可用空间大小。接下来可以看到该值能够影响 acceptNewTasks 值。

当 acceptNewTasks==true 时,即初步判断可以接收新任务,会再次根据 localMinSpaceStart 判断是否可接收新任务。

/**
* Check if any of the local directories has enough
* free space (more than minSpace)
*
* If not, do not try to get a new task assigned
* @return
* @throws IOException
*/
private boolean enoughFreeSpace(long minSpace) throws IOException {
if (minSpace == 0) {
return true;
}
return minSpace < getFreeSpace();
}

private long getFreeSpace() throws IOException {
long biggestSeenSoFar = 0;
String[] localDirs = localStorage.getDirs();
for (int i = 0; i < localDirs.length; i++) {
DF df = null;
if (localDirsDf.containsKey(localDirs[i])) {
df = localDirsDf.get(localDirs[i]);
} else {
df = new DF(new File(localDirs[i]), fConf);
localDirsDf.put(localDirs[i], df);
}

long availOnThisVol = df.getAvailable();
if (availOnThisVol > biggestSeenSoFar) {
biggestSeenSoFar = availOnThisVol;
}
}

//Should ultimately hold back the space we expect running tasks to use but
//that estimate isn’t currently being passed down to the TaskTrackers
return biggestSeenSoFar;
}

判断方法是获取所有的 lcoalDir,计算出这些目录中可用空间最大一个目录的可用大小,为什么使用最大值作为可用大小,而不是所有目录可用空间总和,是因为 localDir 存放 task 的一些本地信息,这些信息是不能夸目录存放的,所以必须确保有一个目录能够容纳下所有的信息。当计算出 freeSpace 后,根据比较 localMinSpaceStart 值与 freeSpace 的大小决定是否接收新任务。

接下来就是获取 TT 的一些资源信息,如总虚拟内存,总物理内存,可用的虚拟内存,可用的物理内存,CPU 使用情况等。接着将这些值添加到 status 中去,发送给 JT。

5.TaskTracker.transmitHeartBeat:

//add node health information

TaskTrackerHealthStatus healthStatus = status.getHealthStatus();
synchronized (this) {
if (healthChecker != null) {
healthChecker.setHealthStatus(healthStatus);
} else {
healthStatus.setNodeHealthy(true);
healthStatus.setLastReported(0L);
healthStatus.setHealthReport(“”);
}
}

此处是检查 TT 的健康状况。

6.TaskTracker.transmitHeartBeat:

//
// Xmit the heartbeat
//
HeartbeatResponse heartbeatResponse = jobClient.heartbeat(status,
justStarted,
justInited,
askForNewTask,
heartbeatResponseId);

此处通过 RPC 调用 JT 的 heartbeat() 方法。传的参数包括:status——TT 自身的状态信息;justStarted——表示 TT 是否刚启动;justInited——表示 TT 是否刚初始化;askForNewTask——表示是否接收新任务;heartbeatResponseId——上次心跳返回的 responseId。方法的返回值是一个 HeartbeatResponse 对象,具体 JT 内的 heartbeat() 方法如何处理以及 HeartbeatResponse 内容会另外分析。继续往下走。

7.TaskTracker.transmitHeartBeat:

//
// The heartbeat got through successfully!
//
heartbeatResponseId = heartbeatResponse.getResponseId();

synchronized (this) {
for (TaskStatus taskStatus : status.getTaskReports()) {
if (taskStatus.getRunState() != TaskStatus.State.RUNNING &&
taskStatus.getRunState() != TaskStatus.State.UNASSIGNED &&
taskStatus.getRunState() != TaskStatus.State.COMMIT_PENDING &&
!taskStatus.inTaskCleanupPhase()) {
if (taskStatus.getIsMap()) {
mapTotal–;
} else {
reduceTotal–;
}
myInstrumentation.completeTask(taskStatus.getTaskID());
runningTasks.remove(taskStatus.getTaskID());
}
}

// Clear transient status information which should only
// be sent once to the JobTracker
for (TaskInProgress tip: runningTasks.values()) {
tip.getStatus().clearStatus();
}
}

// Force a rebuild of ‘status’ on the next iteration
status = null;

return heartbeatResponse;

首先从 HeartbeatResponse 返回值中获取 heartbeatResponseId。接下来对 TT 中的每个 TaskInProgress 的 status 信息进行判断,如果一个 task 处于 SUCCEEDED/FAILED/KILLED 状态,则表示该 task 已完成(不论是失败还是成功,亦或是被 kill 掉),如果该 task 是一个 map 任务,则 mapTotal 减一,该 task 是一个 reduce 任务,则 reduceTotal 减一,mapTotal/reduceTotal 记录当前 TT 所有处于运行状态(非 SUCCEEDED/FAILED/KILLED 状态)的 task 数量。

myInstrumentation.completeTask(taskStatus.getTaskID()) 此处将该 TT 所有完成任务数加一,runningTasks.remove(taskStatus.getTaskID()) 则是将该 task 从 runningTasks 队列中移除,所以可以知道 runningTasks 中只包含未完成的 task 信息。

接下来是清除 TaskInProgress 的 TaskStatus 的临时信息(diagnosticInfo),从 clearStatus() 方法的注释可以看出 diagnosticInfo 信息只是在 Task 向 TaskTracker,或者 TaskTracker 向 JobTracker 发送一个状态更新信息时的临时诊断信息,所以在发送完成之后需要清除。

到这里整个 TaskTracker 发送心跳信息的过程就完成了,方法返回值是 HeartbeatResponse 对象,即心跳的返回值。

更多 Hadoop 相关信息见 Hadoop 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=13

在 Hadoop 中 JT(JobTracker)与 TT(TaskTracker)之间的通信是通过心跳机制完成的。JT 实现 InterTrackerProtocol 协议,该协议定义了 JT 与 TT 之间的通信机制——心跳。心跳机制实际上就是一个 RPC 请求,JT 作为 Server,而 TT 作为 Client,TT 通过 RPC 调用 JT 的 heartbeat 方法,将 TT 自身的一些状态信息发送给 JT,同时 JT 通过返回值返回对 TT 的指令。

目录

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——TT 篇 http://www.linuxidc.com/Linux/2014-06/103216.htm

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——JT 篇 http://www.linuxidc.com/Linux/2014-06/103217.htm

Hadoop1.2.1 源码解析系列:JT 与 TT 之间的心跳通信机制——命令篇 http://www.linuxidc.com/Linux/2014-06/103218.htm

心跳有三个作用:

1)判断 TT 是否活着

2)报告 TT 的资源情况以及任务运行情况

3)为 TT 发送指令(如运行 task,kill task 等)

下面详细阅读下涉及到心跳调用的源码。

首先我们需要清楚,心跳机制是 TT 调用 JT 的方法,而非 JT 主动调用 TT 的方法。TT 通过 transmitHeartBeat 方法调用 JT 的 heartbeat 方法。

1.TaskTracker.transmitHeartBeat:

// Send Counters in the status once every COUNTER_UPDATE_INTERVAL
    boolean sendCounters;
    if (now > (previousUpdate + COUNTER_UPDATE_INTERVAL)) {
      sendCounters = true;
      previousUpdate = now;
    }
    else {
      sendCounters = false;
    }

根据 sendCounters 的间隔判断此次心跳是否发送计算器信息。
 
2.TaskTracker.transmitHeartBeat:

1.TaskTracker.transmitHeartBeat:

// Check if the last heartbeat got through…
    // if so then build the heartbeat information for the JobTracker;
    // else resend the previous status information.
    //
    if (status == null) {
      synchronized (this) {
        status = new TaskTrackerStatus(taskTrackerName, localHostname,
                                      httpPort,
                                      cloneAndResetRunningTaskStatuses(
                                        sendCounters),
                                      taskFailures,
                                      localStorage.numFailures(),
                                      maxMapSlots,
                                      maxReduceSlots);
      }
    } else {
      LOG.info(“Resending ‘status’ to ‘” + jobTrackAddr.getHostName() +
              “‘ with reponseId ‘” + heartbeatResponseId);
    }

此处根据 status 变量是否为 null,判断上次的心跳是否成功发送。tatus!=null,则表示上次的心跳尚未发送,所以直接将上次收集到的 TT 状态信息(封装在 status 中)发送给 JT;相反,status==null,则表示上次心跳已完成,重新收集 TT 的状态信息,同样封装到 status 中。下面详细看下 new TaskTrackerStatus()方法。注意此处有个 cloneAndResetRunningTaskStatuses(sendCounters) 方法:

private synchronized List<TaskStatus> cloneAndResetRunningTaskStatuses(
                                          boolean sendCounters) {
    List<TaskStatus> result = new ArrayList<TaskStatus>(runningTasks.size());
    for(TaskInProgress tip: runningTasks.values()) {
      TaskStatus status = tip.getStatus();
      status.setIncludeCounters(sendCounters);
      // send counters for finished or failed tasks and commit pending tasks
      if (status.getRunState() != TaskStatus.State.RUNNING) {
        status.setIncludeCounters(true);
      }
      result.add((TaskStatus)status.clone());
      status.clearStatus();
    }
    return result;
  }

该方法中涉及到 runningTasks 队列,该队列保存了该 TT 上接收的所有未完成的 Task 任务,通过 runningTasks.values() 可以获取 TT 当前所有未完成的 Task,然后获取每个 TaskInProgress 的 status 信息,同时根据第一步判断出的 sendCounters(true/false)决定是否发送 counters 信息(includeCounters),即是否将 counters 对象序列化到 TaskStatus 对象中,这里需要注意如果 TaskInProgress 不处于 Running 状态,则 includeCounters 设为 true,即发送 counters 信息。

————————————– 分割线 ————————————–

Ubuntu 13.04 上搭建 Hadoop 环境 http://www.linuxidc.com/Linux/2013-06/86106.htm

Ubuntu 12.10 +Hadoop 1.2.1 版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm

Ubuntu 上搭建 Hadoop 环境(单机模式 + 伪分布模式)http://www.linuxidc.com/Linux/2013-01/77681.htm

Ubuntu 下 Hadoop 环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm

单机版搭建 Hadoop 环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm

Hadoop LZO 安装教程 http://www.linuxidc.com/Linux/2013-01/78397.htm

Hadoop 集群上使用 Lzo 压缩 http://www.linuxidc.com/Linux/2012-05/60554.htm

————————————– 分割线 ————————————–

3.TaskTrackerStatus():

public TaskTrackerStatus(String trackerName, String host,
                          int httpPort, List<TaskStatus> taskReports,
                          int taskFailures, int dirFailures,
                          int maxMapTasks, int maxReduceTasks) {
    this.trackerName = trackerName;
    this.host = host;
    this.httpPort = httpPort;

    this.taskReports = new ArrayList<TaskStatus>(taskReports);
    this.taskFailures = taskFailures;
    this.dirFailures = dirFailures;
    this.maxMapTasks = maxMapTasks;
    this.maxReduceTasks = maxReduceTasks;
    this.resStatus = new ResourceStatus();
    this.healthStatus = new TaskTrackerHealthStatus();
  }

这里只是进行简单的变量复制操作,分析下其中一些参数的含义:

1)taskReports:包含该 TT 上目前所有的 Task 状态信息,其中的 counters 信息会根据之前判断 sendCounters 值进行决定是否发送,上一步有提到。

2)taskFailures:该 TT 上失败的 Task 总数(重启会清空),该参数帮助 JT 决定是否向该 TT 提交 Task,因为失败数越多表明该 TT 可能出现 Task 失败的概率越大。

3)dirFailures:这个值是 mapred.local.dir 参数设置的目录中有多少是不可用的(以后会详细提到)

4)maxMapSlots/maxReduceSlots:这个值是 TT 可使用的最大 map 和 reduce slot 数量

初始化完成,继续回到 TaskTracker.transmitHeartBeat 方法。

4.TaskTracker.transmitHeartBeat:

 // Check if we should ask for a new Task
    //
    boolean askForNewTask;
    long localMinSpaceStart;
    synchronized (this) {
      askForNewTask =
        ((status.countOccupiedMapSlots() < maxMapSlots ||
          status.countOccupiedReduceSlots() < maxReduceSlots) &&
        acceptNewTasks);
      localMinSpaceStart = minSpaceStart;
    }
    if (askForNewTask) {
      askForNewTask = enoughFreeSpace(localMinSpaceStart);
      long freeDiskSpace = getFreeSpace();
      long totVmem = getTotalVirtualMemoryOnTT();
      long totPmem = getTotalPhysicalMemoryOnTT();
      long availableVmem = getAvailableVirtualMemoryOnTT();
      long availablePmem = getAvailablePhysicalMemoryOnTT();
      long cumuCpuTime = getCumulativeCpuTimeOnTT();
      long cpuFreq = getCpuFrequencyOnTT();
      int numCpu = getNumProcessorsOnTT();
      float cpuUsage = getCpuUsageOnTT();

      status.getResourceStatus().setAvailableSpace(freeDiskSpace);
      status.getResourceStatus().setTotalVirtualMemory(totVmem);
      status.getResourceStatus().setTotalPhysicalMemory(totPmem);
      status.getResourceStatus().setMapSlotMemorySizeOnTT(
          mapSlotMemorySizeOnTT);
      status.getResourceStatus().setReduceSlotMemorySizeOnTT(
          reduceSlotSizeMemoryOnTT);
      status.getResourceStatus().setAvailableVirtualMemory(availableVmem);
      status.getResourceStatus().setAvailablePhysicalMemory(availablePmem);
      status.getResourceStatus().setCumulativeCpuTime(cumuCpuTime);
      status.getResourceStatus().setCpuFrequency(cpuFreq);
      status.getResourceStatus().setNumProcessors(numCpu);
      status.getResourceStatus().setCpuUsage(cpuUsage);
    }

从源码中的注释可以知道,此处是 TT 根据自身资源使用情况判断是否接收 new task。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-06/103216p2.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计16110字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7994772
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
升级自动部署更新SSL证书系统、申请godaddy的APIKEY

升级自动部署更新SSL证书系统、申请godaddy的APIKEY

升级自动部署更新 SSL 证书系统、申请 godaddy 的 APIKEY 公司之前花钱购买的 ssl 证书快...
免费领取huggingface的2核16G云服务器,超简单教程

免费领取huggingface的2核16G云服务器,超简单教程

免费领取 huggingface 的 2 核 16G 云服务器,超简单教程 前言 HuggingFace.co...
如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的 Nano Banana Pro?附赠邪修的用法 前言 大家好,我是星哥,今天来介绍谷歌的 ...
仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

还在忍受动辄数百兆的“全家桶”监控软件?后台偷占资源、界面杂乱冗余,想查个 CPU 温度都要层层点选? 今天给...
星哥带你玩飞牛NAS-1:安装飞牛NAS

星哥带你玩飞牛NAS-1:安装飞牛NAS

星哥带你玩飞牛 NAS-1:安装飞牛 NAS 前言 在家庭和小型工作室场景中,NAS(Network Atta...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛 NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手! 作为动漫爱好者,你是否还在为...
零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face 免费服务器 +Docker 快速部署 HertzBeat 监控平台 ...
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸 前言 作为天天跟架构图、拓扑图死磕的...
星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛 NAS-11:咪咕视频订阅部署全攻略 前言 在家庭影音系统里,NAS 不仅是存储中心,更是内容...