

(2)补充,对于任务型,比如推送,也会有一个推送延迟的要求,可用n1来压测取得其吞吐量和响应时间,对比是否在要求以内


实测数据:
线程数 吞吐量 响应时间
1 0.5 2
2 1 2
3 1.5 2
4 2 2
5 2 2.5
6 2 3
40 2 20
测试代码:
import java.util.concurrent.*;
/**
* https://www.cnblogs.com/silyvin/p/11806859.html
* https://www.cnblogs.com/silyvin/p/11875907.html
* Created by joyce on 2019/11/6.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
@Threads(40)
@State(Scope.Thread)
public class MyThread {
private static final ThreadPoolExecutor MQ_POOL = new ThreadPoolExecutor(
4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
new DefaultThreadFactory("mq-", true));
public static class action implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int a = 0;
Thread.sleep(2000);
System.out.println(a);
return a;
}
}
@Benchmark
public static void testS() {
try {
Future<Integer> i = MQ_POOL.submit(new action());
i.get();
} catch (RejectedExecutionException e) {
System.out.println("放弃");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String [] f) throws RunnerException {
// jhm压力测试
Options opt = new OptionsBuilder().include(MyThread.class.getSimpleName()).forks(1).warmupIterations(0)
.measurementIterations(1).build();
new Runner(opt).run();
// 自己的压力测试
MyYali.start(40);
}
private static class MyYali implements Runnable {
public static void start(int threadCount) {
for(int i=0; i<threadCount; ++i) {
new Thread(new MyYali()).start();
}
}
// 这个地方如果用1不会出错
private int count = 2;
@Override
public void run() {
for(int i=0; i<count; ++i) {
testS();
}
}
}
}
这里使用LinkedBlockingQueue无界队列来接收等待队列,之后将会详解
引用:
https://blog.csdn.net/sinat_34976604/article/details/88125707
单线程场景:
假设我们的服务端只有一个线程,那么所有的请求都是串行执行,我们可以很简单的算出系统的QPS,也就是:QPS = 1000ms/RT。假设一个RT过程中CPU计算的时间为49ms,CPU Wait Time 为200ms,那么QPS就为1000/(49+200) = 4.01。
多线程场景
我们接下来把服务端的线程数提升到2,那么整个系统的QPS则为:2 *(1000/(49+200))=8.02。可见QPS随着线程的增加而线性增长,那QPS上不去就加线程呗,听起来很有道理,公式也说得通,但是往往现实并非如此,后面会聊这个问题。
最佳线程数?
从上面单线程场景来看,CPU Wait time为200ms,你可以理解为CPU这段时间什么都没做,是空闲的,显然我们没把CPU利用起来,这时候我们需要启多个线程去响应请求,把这部分利用起来,那么启动多少个线程呢?我们可以估算一下 空闲时间200ms,我们要把这部分时间转换为CPU Time,那么就是(200+49)/49 = 5.08个,不考虑上下文切换的话,约等于5个线程。
。。。。。。。。。
通过上面一些例子,我们发现当线程数增加的时候,线程的上下文切换会增加,GC Time会增加。这也就导致CPU time 增加,QPS减小,RT也会随着增大。这显然不是我们希望的,我们希望的是在核数一定的情况下找到某个点,使系统的QPS最大,RT相对较小。所以我们需要不断的压测,调整线程池,找到这个QPS的峰值,并且使CPU的利用率达到100%,这样才是系统的最大QPS和最佳线程数。
https://elasticsearch.cn/question/4350
顺着楼上大牛的思路,现有业务场景下,评估一下你的线程池模型是否合理
举个例子:
一个节点假设配置search线程池为16,队列长度为1000, 一个线程处理一个搜索请求处理耗时是20ms,那么一个线程一秒可以处理50个请求。 那么理论上16个线程一秒可以处理900个请求,1000+16的线程队列大小是能够容纳qps为900的业务的(当然这是理论上,没有考虑的线程上下文切换,网络原因,内存GC导致stw等等,所以实际值肯定比这个低)。
与“n决定吞吐量,L决定响应时间”一致
https://blog.csdn.net/qq_34417408/article/details/78895573
先由之前遇到的一个测试题说起,假设要求一个系统的TPS(Transaction Per Second或者Task Per Second)至少为20,然后假设每个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s。那么问题转化为:
如何设计线程池大小,使得可以在1s内处理完20个Transaction?
计算过程很简单,每个线程的处理能力为0.25TPS,那么要达到20TPS,显然需要20/0.25=80个线程。(理论上)