使用hadoop官方工具遇到了一些问题(附录详写),所以自己编写了测试用例进行压力测试
首先pom文件引入lombok,hadoop和hdfs的依赖包
<properties>
<lombok.version>1.16.20</lombok.version>
<hadoop.version>2.7.7</hadoop.version>
</properties>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
下面是我编写的测试用例(需要配置的注释已给出,需要配置的路径需要自行配置),编译后直接放到一台有linux服务器上进行测试,测试命令为
java -cp./*; hadoop.HLT
其中-cp./*是要引入测试用例需要的jar包,请把项目打包后获取lib下的jar包
import lombok.SneakyThrows;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClassName HadoopLinuxTest
* @Descriptiom TODO hadoop I/O test for linux
* @Author KING
* @Date 2019/4/1 17:26
* @Version 1.2.1
**/
public class HLT implements Runnable
{
//测试文件地址
private static final String src = "/root/32KB" ;
//hadoop namenode 节点ip
private static final String remote = "hdfs://192.168.1.191:9000/";
//设定文件数偏移(用于中继上传)
private static final int Offset = 0;
//上传文件总数
private static final int TOTAL_FILES = 100000000;
//上传文件使用线程数
private static final int TOTAL_THREADS = 200 ;
private String dst ;
private int FileStartNum;
private int FileEndNum;
private Configuration conf;
private CountDownLatch Latch;
public HLT(String dst, int fileStartNum, int fileEndNum, Configuration conf, CountDownLatch latch) {
this.dst = dst;
FileStartNum = fileStartNum;
FileEndNum = fileEndNum;
this.conf = conf;
Latch = latch;
}
@SneakyThrows
public static void main(String[] args) {
ExecutorService ThreadPool = Executors.newFixedThreadPool(TOTAL_THREADS);
CountDownLatch Latch = new CountDownLatch(TOTAL_THREADS);
Configuration conf = new Configuration() ;
conf.set("fs.defaultFS", "hdfs://192.168.1.191:9000"); // "hdfs://master:9000"
int SingleFileNum = TOTAL_FILES/TOTAL_THREADS;
File file = new File("/root/record.txt");
FileOutputStream fileOut = new FileOutputStream(file,true);
Long a = System.currentTimeMillis();
String st ="start time sec :" + a +"\n";
fileOut.write(st.getBytes());
for (int i=0;i<TOTAL_THREADS;i++){
int FileStartNum = i * SingleFileNum + Offset;
int FileEndNum = (i+1) * SingleFileNum;
//hadoop每个文件夹都有文件数量上限,所以此处为每个线程执行的上传新建一个目录
String dst =remote + "linux_test"+i+"/";
HLT hlt = new HLT(dst, FileStartNum, FileEndNum, conf ,Latch);
ThreadPool.execute(hlt);
}
Latch.await();
Long b = System.currentTimeMillis();
String et ="end time sec :" + b +"\n";
fileOut.write(et.getBytes());
String allt = "all time :" + ((b-a)/1000) + "s" +"\n";
fileOut.write(allt.getBytes());
System.out.println("总用时:" + ((b-a)/1000) + "s");
ThreadPool.shutdown();
}
@Override
public void run() {
//hadoop目录未指定时启用,修改为自己hadoop的根目录
// System.setProperty("hadoop.home.dir", "/root/hadoop-2.7.1");
//用户名为非root时启用
// System.setProperty("HADOOP_USER_NAME", "root");
for (int n = FileStartNum; n < FileEndNum ; n++){
putToHDFS(src, dst + n, conf);
}
Latch.countDown();
}
/** 执行hadoop上传操作
* @param src 本地资源全路径
* @param dst 远程地址全路径
* @param conf 对hadoop的设置
* @return boolean 是否上传成功
*/
public static boolean putToHDFS(String src , String dst , Configuration conf){
Path dstPath = new Path(dst) ;
try{
FileSystem hdfs = dstPath.getFileSystem(conf) ;
hdfs.copyFromLocalFile(false, new Path(src), dstPath) ;
}
catch(IOException ie){
ie.printStackTrace() ;
return false ;
}
return true ;
}
}
测试环境参数记录
类别 | 型号 | 标准值 | 实际测试差异记录 |
---|---|---|---|
磁盘参数 | 磁盘型号 | ST1000NM0018-2F2130 | |
- | 磁盘类型 | SATA-7200RPM | SATA-7200RPM |
- | 厂商 | DELL | |
- | 单盘容量(GB) | 1TB | |
- | FW版本 | EA04 | |
- | 磁盘所在位置 | SPU:2个磁盘DSU2624(DSU-1:1:2):3个磁盘DSU2624(DSU-1:2:1):3个磁盘 | |
HADOOP环境参数 | H节点个数 | 8个 | |
- | 虚拟机CPU/内存 | 16线程/64GB内存 | |
- | 前端网络 | 10GE | 客户端为10GE,通过交换机连接10GE网络 |
- | 后端网络 | 10GE | 同左 |
- | 其他 | 标准V2.7.7版本 | |
客户端参数 | 操作系统 | CentOS Linux release 7.6.1810 (Core) | |
- | 内存 | 8GB | |
- | CPU | Intel® Xeon® CPU E5-2609 v3 @ 1.90GHz(双CPU,每个CPU 6核12线程) | |
- | 访问hadoop速率 | 10Gb/s | |
- | 并发线程数 | 详见测试参数 | |
- | 文件大小 | 32KB | |
- | 文件数量 | 100000000 | |
- | 其他 |
测试结果如下
200并发情况下上传一亿个32KB文件
操作总数 | 字节数 | 平均响应时间 | 平均处理时间 | 吞吐量 | 带宽 | 总用时 |
---|---|---|---|---|---|---|
100000000File | 2.9795TB | 1.08 ms | 2.08 ms | 481.25op/s | 15.03MB/S | 207792.21s≈58h |
附录
官方工具的问题
1.速度奇慢
hadoop jar /home/hadoop/hadoop-2.7.7/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.7-tests.jar TestDFSIO -write -nrFiles 10000 -size 32KB
这是官方的 TestDFSIO方法,蜗牛一般的速度,报异常还不少,远达不到hdfs的性能瓶颈
2.TestDFSIO只能测试一个节点的性能,所有文件都会写在当前运行TestDFSIO方法的节点上,完全不是集群的压力测试,是单节点的测试。
3.teragen 工具
hadoop jar /home/hadoop/hadoop-2.7.7/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.7.jar teragen -Dmapred.map.tasks=100000000 -Ddfs.block.size=134217728 32 /terasort/output
以上命令虽然定义了任务数量 -Dmapred.map.tasks=100000000,但事实上这个参数毫无作用,不论怎么设定这个参数,teragen 工具只能创建一个文件。然后无看了源码和官方介绍,teragen 工具只是为了给terasort测试工具生成一个测试用例,并不是什么压力测试工具。(网上的博客好深的水)