压测小工具
文章目录
最近给某东西压测(由于是私有协议没有通用工具可用),就自己写了个可以给压力的工具,可以支持QPS显示和响应时间的分布显示,有兴趣的可以拿来玩玩
sql压测使用样例:
import groovy.sql.Sql
/**
* @author <a href="mailto:wentong@taobao.com"></a>
* @since 11-11-9 2:00
*
*/
def client_num = 100
private List<Sql> connent(int num) {
def result = []
1.upto(num) {result.add(Sql.newInstance("jdbc:mysql://127.0.0.1:3306/sbtest", "test", "test", "com.mysql.jdbc.Driver"))}
return result
}
def clients = connent(client_num)
def getId() {
def total\_record\_num = 80000000
def hot = 20
def step = 100 / hot
BigDecimal hot\_range = total\_record_num / step
if (RandomTest.nextInt(100) < 95) {
return RandomTest.getId(hot_range, 1).intValue().toString()
} else {
return RandomTest.getId(total\_record\_num, 1).intValue().toString()
}
}
def s = new StressTest()
s.add({
Sql client = clients.get(it)
client.execute("select id ,k,c,pad from sbtest where id =" + getId())
}, client_num)
s.run()
clients.each {it.close()}
`</pre>
StressTest 源码:
<pre>`import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicLong
/**
* @author <a href="mailto:wentong@taobao.com"></a>
* @since 11-11-9 1:12
*
*/
class StressTest {
int interval = 1; //s
int count = 0;
int time = 0;
boolean print_rt = true
private final AtomicLong MONITOR\_STAT\_QPS_NUM = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_TOTAL = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_0MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_0_1MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_1_5MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_5_10MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_10_50MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_50_100MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_100_500MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_500_1000MS = new AtomicLong();
private final AtomicLong MONITOR\_RESPNSE\_1000_MS = new AtomicLong();
private final ThreadLocal<Long> START_TIME = new ThreadLocal<Long>();
private Map<Closure, Integer> closures = new HashMap<Closure, Integer>();
private int thread_num = 0;
private AtomicInteger stop\_thread\_num = new AtomicInteger();
private ExecutorService pool;
private boolean is_stop = false
/**
* Method start ...
*/
private void start() {
START_TIME.set(System.currentTimeMillis());
}
/**
* Method end ...
*/
private void end() {
long start = START_TIME.get();
long response = System.currentTimeMillis() - start;
MONITOR\_STAT\_QPS_NUM.incrementAndGet();
MONITOR\_RESPNSE\_TOTAL.incrementAndGet();
if (response <= 0) {
MONITOR\_RESPNSE\_0MS.incrementAndGet();
} else if (response > 0 && response <= 1) {
MONITOR\_RESPNSE\_0_1MS.incrementAndGet();
} else if (response > 1 && response <= 5) {
MONITOR\_RESPNSE\_1_5MS.incrementAndGet();
} else if (response > 5 && response <= 10) {
MONITOR\_RESPNSE\_5_10MS.incrementAndGet();
} else if (response > 10 && response <= 50) {
MONITOR\_RESPNSE\_10_50MS.incrementAndGet();
} else if (response > 50 && response <= 100) {
MONITOR\_RESPNSE\_50_100MS.incrementAndGet();
} else if (response > 100 && response <= 500) {
MONITOR\_RESPNSE\_100_500MS.incrementAndGet();
} else if (response > 500 && response <= 1000) {
MONITOR\_RESPNSE\_500_1000MS.incrementAndGet();
} else if (response > 1000) {
MONITOR\_RESPNSE\_1000_MS.incrementAndGet();
}
}
public void add(Closure closure, int threadNum) {
closures.put(closure, threadNum)
this.thread_num += threadNum
}
public void run() {
pool = Executors.newFixedThreadPool(thread_num + 1)
def defer = { c -> pool.submit(c as Runnable) }
closures.each { c ->
if (c.value > 0) {
1.upto(c.value) { idx ->
defer {runit(c.key, idx - 1)}
}
}
}
defer {monitor()}
pool.shutdown()
while (!pool.awaitTermination(1000, TimeUnit.SECONDS)) {
}
println "#######################################"
}
private void runit(Closure closure, int i) {
int c = count / thread_num;
try {
while (!is_stop && (count == 0 || c > 0)) {
try {
start()
closure.call(i)
} finally {
end()
if (c > 0) {
c--
}
}
}
} finally {
stop\_thread\_num.incrementAndGet()
}
}
/**
* Method run ...
*/
private void monitor() {
println("start monitor")
long start_time = System.currentTimeMillis()
long end\_time = start\_time + (time * 1000);
while (stop\_thread\_num.get() < thread_num) {
if (time > 0 && System.currentTimeMillis() >= end_time) {
println "time is over"
is_stop = true
}
Thread.sleep(interval * 1000);
long num = MONITOR_STAT_QPS_NUM.getAndSet(0);
println(&quot;QPS:&quot; + (num / interval) + &quot; TOTAL:&quot; + MONITOR_RESPNSE_TOTAL.get());
if (print_rt) {
print_rt();
}
println(&quot;----------------------------------&quot;);
}
def total_time = (System.currentTimeMillis() - start_time) / 1000
println &quot;avg QPS:&quot; + MONITOR_RESPNSE_TOTAL.get() / total_time + &quot; ,total:&quot; + MONITOR_RESPNSE_TOTAL.get()
print_rt()
println(&quot;end monitor&quot;)
}
private def print_rt() {
long total = MONITOR\_RESPNSE\_TOTAL.get();
println(" RT <= 0: " + (MONITOR\_RESPNSE\_0MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_0MS.get() + "/" + total);
println(" RT (0,1]: " + (MONITOR\_RESPNSE\_0_1MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_0_1MS.get() + "/" + total);
println(" RT (1,5]: " + (MONITOR\_RESPNSE\_1_5MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_1_5MS.get() + "/" + total);
println(" RT (5,10]: " + (MONITOR\_RESPNSE\_5_10MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_5_10MS.get() + "/" + total);
println(" RT (10,50]: " + (MONITOR\_RESPNSE\_10_50MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_10_50MS.get() + "/" + total);
println(" RT (50,100]: " + (MONITOR\_RESPNSE\_50_100MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_50_100MS.get() + "/" + total);
println(" RT (100,500]: " + (MONITOR\_RESPNSE\_100_500MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_100_500MS.get() + "/" + total);
println(" RT (500,1000]:" + (MONITOR\_RESPNSE\_500_1000MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_500_1000MS.get() + "/" + total);
println(" RT > 1000: " + (MONITOR\_RESPNSE\_1000_MS.get() * 100 / total) + "% " +
MONITOR\_RESPNSE\_1000_MS.get() + "/" + total)
}
}