测试简介
底层数据库采用Hbase,可视化工具使用的是Phoenix。
作业由来:甲方想通过jmete对hbase进行压测,但是上线的两个接口并没有封装成http协议,没办法直接调用,百度的dubbo-jmeter-plugin添加之后也没有连接成功,一番挣扎之后放弃了,所以就准备自己写个并发程序去测试一下。
测试主要是看查询的QPS(每秒查询效率),计算公式:总请求数/总执行时间(总请求数是为测试数据量)。废话不多说直接上测试代码。
代码
程序入口:
/**
* 自己编写Java高并发对dubbo服务接口的查询功能进行压力测试
* @author Lenovo
*
*/
public class MainApplication {
private static ClassPathXmlApplicationContext context;
private static AtomicInteger atomicInteger;
//dubbo消费者的启动入口
public static void main( String[] args )
{
context = new ClassPathXmlApplicationContext("dubbo-consumer.xml");
//此处为自己的接口
Test test = context.getBean("Test");
context.start();
//读取测试数据文件
File file = new File("F:\\test_data\\book\\data.txt");
BufferedReader bufferedReader;
LineNumberReader lineNumberReader;
List<String> list;
try {
bufferedReader = new BufferedReader(new FileReader(file));
lineNumberReader = new LineNumberReader(bufferedReader);
String str = "";
list = new ArrayList<String>();
while((str = lineNumberReader.readLine()) != null) {
list.add(str);
}
} finally {
bufferedReader.close();
lineNumberReader.close();
}
//将读取进来的数据打乱
Collections.shuffle(list);
//初始化线程池
ExecutorService executorService = Executors.newFixedThreadPool(32);
//开始记录调用接口到所有数据查询完毕的时间
Long currentTime = System.currentTimeMillis();
for(int i = 0; i<list.size();i++) {
Runnable runnable = execute(test,list.get(i).split(","));
executorService.execute(runnable);
}
//关闭线程池
executorService.shutdown();
//等待线程池中的所有线程执行完再执行主函数
while(!executorService.isTerminated()) {}
Long stillTime = System.currentTimeMillis()-currentTime;
System.out.println("总执行时间(ms):"+stillTime);
System.out.println("总数据量"+atomicInteger);
System.out.println("QPS为:"+(atomicInteger.longValue())/stillTime);
}
private static Runnable execute(Test test,String[] value) {
Runnable runnable = new Runnable() {
@Override
public void run() {
test.get(value[0],value[1],value[2]);
atomicInteger.addAndGet(1);
}
};
return runnable;
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费方的应用名,用于计算依赖关系,不是匹配条件,不要与消费方一致 -->
<dubbo:application name="test"></dubbo:application>
<!-- 走的zk注册中心,即dubbo服务注册的zk地址 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1"/>
<dubbo:annotation package="com.bigdata.test"/>
<dubbo:reference id="TestSearch" interface="com.bigdata.test.api.TestSearch" />
</beans>
测试结果分析
最终的测试结果QPS只有几十,并没有达到我们的预期,所以接下来就开始找到底是哪里有问题了。
1.首先将关联查询的sql单独拆开,也就是单表查询。内层的单表速度非常快,因为查询的条件是走的row_key精准查询,QPS在2000以上。接下来就开始找外层的sql,果不其然,QPS非常的低。
2.外层的查询条件走了row_key联合索引的第一个,那我们就考虑可不可以直接将row_key改为,直接否定了,因为这样会导致部分数据丢失,那我们又开始考虑是不是对表加盐加多了,导致数据过于散列。
3.我们试着将分区从100改为了10,QPS一下就上去了,提升了大概有百倍。
总结
导致QPS低的原因有很多,常见的有:
1.数据库表从建表的时候考虑不周到,没有很好的建立row_key;
2.设置分区不合理,导致数据过于散列;
3.服务器的性能比较差;
由于本人经验不足,可能分析的比较浅显,如果表达有不对的地方,希望各位大佬可以指教。