文章目录

最近给某东西压测(由于是私有协议没有通用工具可用),就自己写了个可以给压力的工具,可以支持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 &lt;a href="mailto:wentong@taobao.com"&gt;&lt;/a&gt;  
* @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&lt;Long&gt; START_TIME = new ThreadLocal&lt;Long&gt;();

private Map&lt;Closure, Integer&gt; closures = new HashMap&lt;Closure, Integer&gt;();

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 &lt;= 0) {  
MONITOR\_RESPNSE\_0MS.incrementAndGet();  
} else if (response &gt; 0 &amp;&amp; response &lt;= 1) {  
MONITOR\_RESPNSE\_0_1MS.incrementAndGet();  
} else if (response &gt; 1 &amp;&amp; response &lt;= 5) {  
MONITOR\_RESPNSE\_1_5MS.incrementAndGet();  
} else if (response &gt; 5 &amp;&amp; response &lt;= 10) {  
MONITOR\_RESPNSE\_5_10MS.incrementAndGet();  
} else if (response &gt; 10 &amp;&amp; response &lt;= 50) {  
MONITOR\_RESPNSE\_10_50MS.incrementAndGet();  
} else if (response &gt; 50 &amp;&amp; response &lt;= 100) {  
MONITOR\_RESPNSE\_50_100MS.incrementAndGet();  
} else if (response &gt; 100 &amp;&amp; response &lt;= 500) {  
MONITOR\_RESPNSE\_100_500MS.incrementAndGet();  
} else if (response &gt; 500 &amp;&amp; response &lt;= 1000) {  
MONITOR\_RESPNSE\_500_1000MS.incrementAndGet();  
} else if (response &gt; 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 -&gt; pool.submit(c as Runnable) }  
closures.each { c -&gt;  
if (c.value &gt; 0) {  
1.upto(c.value) { idx -&gt;  
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 &amp;&amp; (count == 0 || c &gt; 0)) {  
try {  
start()  
closure.call(i)  
} finally {  
end()  
if (c &gt; 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() &lt; thread_num) {  
if (time &gt; 0 &amp;&amp; System.currentTimeMillis() &gt;= end_time) {  
println "time is over"  
is_stop = true  
}  
Thread.sleep(interval * 1000);

      long num = MONITOR_STAT_QPS_NUM.getAndSet(0);
      println(&amp;quot;QPS:&amp;quot; + (num / interval) + &amp;quot; TOTAL:&amp;quot; + MONITOR_RESPNSE_TOTAL.get());

      if (print_rt) {
        print_rt();
      }
      println(&amp;quot;----------------------------------&amp;quot;);
    }

    def total_time = (System.currentTimeMillis() - start_time) / 1000

    println &amp;quot;avg QPS:&amp;quot; + MONITOR_RESPNSE_TOTAL.get() / total_time + &amp;quot; ,total:&amp;quot; + MONITOR_RESPNSE_TOTAL.get()
    print_rt()
    println(&amp;quot;end monitor&amp;quot;)

}

private def print_rt() {  
long total = MONITOR\_RESPNSE\_TOTAL.get();  
println(" RT &lt;= 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 &gt; 1000: " + (MONITOR\_RESPNSE\_1000_MS.get() * 100 / total) + "% " +  
MONITOR\_RESPNSE\_1000_MS.get() + "/" + total)  
}  
}
文章目录