使用JAVA代码模拟(高)并发请求情况
作者:互联网
想要测试并发的请求方式有很多工具,例如Jmeter就是一个很好的测试软件。
因为电脑上没有安装类似的工具,就想用JAVA代码直接模拟。
一、实现思路
1、通过Jsoup进行网络数据的请求
2、通过多线程实现多个请求。
3、使用CountDownLatch控制并发请求。
二、代码实现
导入Jsoup
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
在main方法中请求需要的地址
public static void main(String[] args) throws IOException {
//如果需要参数就使用data()方法
System.out.println(Jsoup.connect("http://www.baidu.com").get());
}
执行后查看结果
jsoup是吧请求到的html代码都返回回来了,有这个就代表请求成功了。
请求成功后,就可以进行高并发的测试了。
public class HighConcurrent {
public static void main(String[] args) throws IOException {
// 发起100个请求
for (int i = 0; i < 100; i++) {
new Thread(new SomeRunable()).start();
}
Thread.sleep(5000);
// 计数器-1(归零),发起并发请求
cdl.countDown();
}
/**计数器*/
private static CountDownLatch cdl = new CountDownLatch(1);
static class SomeRunable implements Runnable {
@Override
public void run() {
try {
// 阻塞线程,直到计数器归零
cdl.await();
Jsoup.connect("http://www.baidu.com").get();
System.out.println(Thread.currentThread().getName()+ ":请求完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
// 发起url请求
catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里我还是比较客气的,只写了100个线程去请求百度。结果如下:
思路和总结
通过main方法创建100(或更多)个线程,这些进程被await()方法所阻塞。等待5秒之后,计数器归零,cdl立刻返回(所有的进行结束等待,进行执行下一行代码)。这些请求在同一时间被发出。如此模拟成一个(高)并发的请求。
另外,为了确定这些请求在1秒内被执行(执行了并不代表已经发送到对方服务器),使用来下面的代码。
结果显示是10000个线程都执行了,在结果中,大部分的请求应该都是 java.net.ConnectException: Connection timed out: connect了。
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.jsoup.Jsoup;
public class HighConcurrent {
public static void main(String[] args) throws IOException, InterruptedException {
// 发起10000个请求
for (int i = 0; i < 10000; i++) {
new Thread(new SomeRunable(), "" + i).start();
}
Thread.sleep(5000);
start=System.currentTimeMillis();
// 计数器-1(归零),发起并发请求
cdl.countDown();
Thread.sleep(2000);
System.out.println(Count.counter.get());
}
/** 计数器 */
private static CountDownLatch cdl = new CountDownLatch(1);
private static long start = 0;
static class SomeRunable implements Runnable {
@Override
public void run() {
try {
// 阻塞线程,直到计数器归零
cdl.await();
if (System.currentTimeMillis() - start > 1000) {
return;
}
Count.add();
Jsoup.connect("http://www.baidu.com").get();
System.out.println(Thread.currentThread().getName() + ":请求完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
// 发起url请求
catch (IOException e) {
e.printStackTrace();
}
}
}
static class Count {
private static AtomicInteger counter = new AtomicInteger(0);
public static void add() {
// 线程安全,以原子方式将当前值加1
counter.getAndIncrement();
}
}
}
之后我设置了超时时间 .timeout(1000000),但是大部分还是timeout了,并且很快就出现了。
具体的原因我还不是很清楚,但是我估计是百度做了部分的拦截功能,当同一IP的qps过高时,会直接丢弃请求。毕竟正常人也不可能一秒钟点个几千次。
题外话:
这个代码简单测试自己的服务器还是不错的,成功的把公司服务器跑崩了。
不过根据这个简单的测试,有两个想法。
1、在高并发情况下,针对同一个IP,并不是所有的请求都需要进行处理。
2、针对上面的情况,可以考虑做个IP黑名单,但是如果别人有意攻击的话,虽说用处不大但也能增加敌人的攻击成本。
标签:JAVA,请求,Thread,cdl,并发,static,new,public,模拟 来源: https://blog.csdn.net/weixin_43593149/article/details/88736687