quarkus - quarkus http 调用负载测试结果 1000 个请求 - 16 秒 vs 65 秒
问题描述
测试1:
@Path("/performance")
public class PerformanceTestResource {
@Timeout(20000)
@GET
@Path("/resource")
@Produces(MediaType.APPLICATION_JSON)
public Response performanceResource() {
final String name = Thread.currentThread().getName();
System.out.println(name);
Single<Data> dataSingle = null;
try {
dataSingle = Single.fromCallable(() -> {
final String name2 = Thread.currentThread().getName();
System.out.println(name2);
Thread.sleep(1000);
return new Data();
}).subscribeOn(Schedulers.io());
} catch (Exception ex) {
int a = 1;
}
return Response.ok().entity(dataSingle.blockingGet()).build();
}
}
测试本身也参见定义callPeriodically
:
@QuarkusTest
public class PerformanceTestResourceTest {
@Tag("load-test")
@Test
public void loadTest() throws InterruptedException {
int CALL_N_TIMES = 1000;
final long CALL_NIT_EVERY_MILLISECONDS = 10;
final LoadTestMetricsData loadTestMetricsData = LoadTestUtils.callPeriodically(
this::callHttpEndpoint,
CALL_N_TIMES,
CALL_NIT_EVERY_MILLISECONDS
);
assertThat(loadTestMetricsData.responseList.size(), CoreMatchers.is(equalTo(Long.valueOf(CALL_N_TIMES).intValue())));
long executionTime = loadTestMetricsData.duration.getSeconds();
System.out.println("executionTime: " + executionTime + " seconds");
assertThat(executionTime , allOf(greaterThanOrEqualTo(1L),lessThan(20L)));
}
结果测试1:
执行时间:16 秒
测试 2:相同但没有 @Timeout注释:
执行时间:65 秒
问:为什么?我认为即使是 16 秒也很慢。问:如何使其更快:假设 1000 次通话需要 2 秒。
我意识到我.blockingGet()
在资源中使用,但我仍然希望重新使用阻塞线程。
PS 我试图更“被动”地返回Single
或 CompletionStage
从响应中返回 - 但这似乎还没有准备好(在轻松休息方面有问题)。所以我选择简单的 .blockingGet()` 和 Response。
更新:反应式 / RX Java 2 方式
@path("/performance")
public class PerformanceTestResource {
//@Timeout(20000)
@GET
@Path("/resource")
@Produces(MediaType.APPLICATION_JSON)
public Single<Data> performanceResource() {
final String name = Thread.currentThread().getName();
System.out.println(name);
System.out.println("name: " + name);
return Single.fromCallable(() -> {
final String name2 = Thread.currentThread().getName();
System.out.println("name2: " + name2);
Thread.sleep(1000);
return new Data();
});
}
}`
io.smallrye smallrye-context-propagation-propagators-rxjava2 org.jboss.resteasy resteasy-rxjava2
然后在运行相同的测试时:
执行时间:64 秒
输出将类似于:
name: vert.x-worker-thread-5 vert.x-worker-thread-9 name: vert.x-worker-thread-9
name2: vert.x-worker-thread-9
name2: vert.x-worker-thread-5
所以,我们阻塞了工作线程,即在 REst/Resource 端使用。就是这样。然后:
如果我use:Schedulers.io()
在 sleep-1000-call 的单独执行上下文中:
return Single.fromCallable(() -> { ... }).subscribeOn(Schedulers.io());
执行时间:16秒
输出将是这样的(见一个新人:RxCachedThreadScheduler)
name: vert.x-worker-thread-5
name2: RxCachedThreadScheduler-1683
vert.x-worker-thread-0
name: vert.x-worker-thread-0
vert.x-worker-thread-9
name: vert.x-worker-thread-9
name2: RxCachedThreadScheduler-1658
vert.x-worker-thread-8
似乎不管:无论我是否明确使用blockingGet()
,我都会得到相同的结果。
我假设如果我不阻止它,它会在2-3 秒左右。
问:我有办法从这一点上修复/调整这个吗?
我假设在这一点上使用Schedulers.io()
它会带来RxCachedThreadScheduler
瓶颈,所以我最终得到16 秒,默认情况下200 io / io 线程是限制?但是那些应该被重用而不是真正被阻止。(不要认为将限制设置为 1000 是个好主意)。
问:或者无论如何:如何让应用程序像 Quarkus 那样具有响应性/反应性/高性能。或者我错过了什么?
谢谢!
解决方案
Ok. Maybe it is me. In my callPeriodically(); i pass CALL_NIT_EVERY_MILLISECONDS = 10 milliseconds. 10 * 1000 = 10 000 - + ten seconds just to add the requests.
This, I set it to 0.
And got my 6 seconds for server 1000 simulations requests.
Still not 2-3 seconds. But 6.
Seems there is no difference if I use .getBlocking
and return Response
or returning Single
.
--
But just to mention it, this hello world app take 1 second to process 1000 parallel requests. While Quarkus one is 6 seconds.
public class Sample2 {
static final AtomicInteger atomicInteger = new AtomicInteger(0);
public static void main(String[] args) {
long start = System.currentTimeMillis();
final List<Single<Response>> listOfSingles = Collections.synchronizedList(new ArrayList<>());
for (int i=0; i< 1000; i++) {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
final Single<Response> responseSingle = longCallFunction();
listOfSingles.add(responseSingle);
}
Single<Response> last = Single.merge(listOfSingles).lastElement().toSingle();
final Response response = last.blockingGet();
long end = System.currentTimeMillis();
System.out.println("Execution time: " + (end - start) / 1000);
System.out.println(response);
}
static Single<Response> longCallFunction() {
return Single.fromCallable( () -> { // 1 sec
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
int code = atomicInteger.incrementAndGet();
//System.out.println(code);
return new Response(code);
}).subscribeOn(Schedulers.io());
}
}
推荐阅读
- c# - 无法加载文件或程序集“Microsoft.VisualStudio.Threading,版本=16.8.0.0
- sql-server - Access 2007 请求 SQL Server 日期和时间
- android-studio - 从“Cold Boot Now”启动时,Android Emulator 恢复到上次状态
- r - 使用 R 绘制稀疏矩阵
- java - Aspectj 中同一方面内建议的顺序
- java - 如何使用 Gatling 负载测试框架执行 Java 代码?
- apache - Docker:(13)权限被拒绝:AH00072:make_sock:无法绑定到地址 0.0.0.0:80
- javascript - 由于引号,我无法检索该字段以将其集成到我的表中您有解决问题的方法吗?
- http - Haskell Socks 客户端请求
- javascript - onClick 方法中的箭头功能?