第七周作业
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
随着并发压力的增加,刚开始系统响应时间应该是稳定的,吞吐量会逐步上升,随之出现排队,锁冲突,这个时候响应时间会上升,吞吐量还是会缓慢提升,直到资源利用率趋于饱和这个时候,因为资源争用,响应时间会进一步提升,吞吐量会呈现下降趋势。
用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
package benchmark;
import java.util.Properties;
public interface Client {
public boolean setUp(Properties prop);
public void test(SampleResult result) ;
public void tearDown();
}
package benchmark;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
public class HttpClient implements Client {
private String urlName ;
@Override
public boolean setUp(Properties prop) {
urlName = prop.getProperty( "URLNAME", "http://www.baidu.com" ) ;
return true ;
}
@Override
public void test(SampleResult result) {
result.sampleStart();
try {
URL url = new URL(urlName);
URLConnection connection;
connection = url.openConnection();
connection.connect();
Map<String, List<String>> headers = connection.getHeaderFields();
BufferedReader br;
br = new BufferedReader(new InputStreamReader(
connection.getInputStream(), StandardCharsets.UTF_8));
String line = "";
while ((line = br.readLine()) != null);
br.close();
} catch ( IOException e1 ) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
result.sampleEnd();
}
@Override
public void tearDown() {
// TODO Auto-generated method stub
}
}
package benchmark;
public class SampleResult {
private long startTime = 0;
private long endTime = 0 ;
public void sampleStart() {
if (startTime == 0) {
startTime = System.currentTimeMillis();
}
}
public void sampleEnd() {
if (endTime == 0) {
endTime = System.currentTimeMillis() ;
}
}
public long getLatency() {
return endTime - startTime ;
}
}
package benchmark;
public interface TestControl {
public boolean isStopTest();
}
package benchmark;
import java.util.concurrent.atomic.AtomicInteger;
public class LoopControl implements TestControl {
private AtomicInteger loopCount ;
public LoopControl(int count) {
this.loopCount = new AtomicInteger(count) ;
}
@Override
public boolean isStopTest() {
// TODO Auto-generated method stub
return this.loopCount.getAndDecrement() <= 0;
}
}
package benchmark;
public interface TestReport {
public void out();
public void addTestResult(SampleResult res) ;
}
package benchmark;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicLong;
public class TxtTestReport implements TestReport {
private AtomicLong totalSpentTime = new AtomicLong(0) ;
private AtomicLong totalTimes = new AtomicLong(0) ;
private Set<Long > result = new TreeSet<Long>() ;
@Override
public void out() {
// TODO Auto-generated method stub
System.out.println("***************************test result *****************************") ;
System.out.println("Avg: " + totalSpentTime.get()*1.0 / totalTimes.get() );
int index = ( int ) ( result.size() * 0.95 ) ;
System.out.println("95th: " + result.toArray()[index]);
}
@Override
public void addTestResult( SampleResult res ) {
// TODO Auto-generated method stub
totalSpentTime.addAndGet( res.getLatency() ) ;
totalTimes.incrementAndGet() ;
synchronized(result) {
result.add( res.getLatency() ) ;
}
}
}
package benchmark;
import java.util.Properties;
public class Executor implements Runnable {
private Client testClient ;
private Properties prop ;
private TestControl testCtrl ;
private TestReport report ;
public Executor(Client client, Properties prop ) {
this.testClient = client ;
this.prop = prop ;
}
public void setTestControl(TestControl testCtrl) {
this.testCtrl = testCtrl ;
}
public void setReport( TestReport report) {
this.report = report ;
}
@Override
public void run() {
if ( testClient.setUp( prop )) {
SampleResult result = new SampleResult() ;
while ( ! testCtrl.isStopTest() ) {
testClient.test(result);
this.report.addTestResult( result );
}
testClient.tearDown();
}
}
}
package benchmark;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
String url ;
int threadCount = 0 ;
int loopCount = 0 ;
for (int i = 0; i < args.length; ++i) {
if ( args[i].equals("--threads") ) {
threadCount = Integer.parseInt( args[++i] );
}else if ( args[i].equals("--url") ) {
url = args[++i];
}else if (args[i].equals("--loopcount")) {
loopCount = Integer.parseInt( args[++i]);
}else {
System.out.println("error input") ;
System.exit( 1 );
}
}
if (threadCount <=0 || loopCount <= 0) {
System.out.println("error input") ;
System.exit( 1 );
}
LoopControl ctrl = new LoopControl(loopCount) ;
TestReport report = new TxtTestReport();
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i <threadCount; ++i) {
Executor executor = new Executor(new HttpClient(), new Properties()) ;
executor.setTestControl( ctrl );
executor.setReport( report );
cachedThreadPool.execute(executor) ;
}
cachedThreadPool.shutdown();
while(!cachedThreadPool.isTerminated()) {
try {
Thread.sleep( 1000 );
} catch ( InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
report.out();
}
}
测试结果
***************************test result *****************************
Avg: 176.91
95th: 328
评论