更多的执行过程信息,我们则通过“org.apache.commons.logging.Log”来收集,通过tasklog页面可以查阅到这些详细的日志信息。

  作为map task的输入,我通过在hdfs上生成的一堆随机数据来实现,InputSplit类读取了hdfs上作为模拟真实数据的输入后,将其根据map数切分成n份(n=自定义的map数量),并将其分发给对应的map task,map task拿到自己那份数据后,立即启动多个线程执行上述测试工具代码:
public void map(LongWritable key, List<Pair> value,
OutputCollector<Text, LongWritable> context, Reporter reporter)
throws IOException {
。。。。。。
for(int i=0; i < this.threadnum; i++){
SCNThread t = new SCNThread(value, reporter, start, this);
t.start();
this.alivethread.addAndGet(1);
}
  。。。。。。
  各task自行同步线程启动数量,当所有线程都启动之后,输出收集器开始运作:
long now = System.currentTimeMillis();
if (now > this.start + this.interval) {
this.start += this.interval;
context.collect(new LongWritable(this.start), new LongWritable(
this.writeBlocks));
}
  。。。。。。
  可以看到key是时间戳,value是我们想收集的数值,收集器收集到的数据将进一步提供给Reducer来分析,这里有一个压力测试的关键点,即大并发开始时间点和结束时间点的判断。观察Reducer类的reduce方法:
  public void reduce(Text key, Iterator<LongWritable> value,
  OutputCollector<Text, Text> context, Reporter reporter)
  由于所有map都以相同的时间戳作为key,因此同一时刻迭代器value的size代表了有多少个map已经达到了大并发度,我们判断这个size,当其与我们预期的map总数一致时,则可以将该时间戳作为大并发压力的开始时间点,当size开始小于预期map总数时,则代表大并发压力的结束时间点,测试结果分析时可以掐取这一段数据作为测试结果,免去开始准备阶段和快结束阶段压力变小对测试结果的干扰。
  更进一步我们可以在hdfs上设计一个标志位,当一个maptask执行完毕之后,通过该标志位通知到其他所有map task,以便快速结束当前的测试。
  测试结果被reducer分析汇总后输出到hdfs上,终我们只需要查看一下这个输出文件的内容可以得到我们需要的测试结果了。
  其实我们不难发现,这种测试框架与DDoS攻击很类似,当手握数千台机器之后,基本上具备了指哪毁哪的能力,MR框架体系蕴藏的能量的确是非常巨大的。