使用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黑名单,但是如果别人有意攻击的话,虽说用处不大但也能增加敌人的攻击成本。

猜你喜欢

转载自blog.csdn.net/weixin_43593149/article/details/88736687
今日推荐