测试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
定义的测试本身see also:
@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()
,但是我仍然希望重新使用阻塞线程。
P.S。
我尝试让更多的“反应性”返回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();
});
}
}`
小黑麦 smallrye上下文传播传播器-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调用的单独执行上下文中:
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是个好主意。)
Q:或无论如何:如何使应用程序像使用Quarkus一样具有响应/反应/性能。还是我想念什么?
谢谢!
答案 0 :(得分:0)
好的。也许是我。 在我的callPeriodically();我通过了CALL_NIT_EVERY_MILLISECONDS = 10毫秒。 10 * 1000 = 10000-+ 10秒仅用于添加请求。
我将其设置为0。
花了我6秒钟来处理服务器1000个模拟请求。
仍然不是2-3秒。但是6。
如果我使用.getBlocking
并返回Response
或返回Single
,似乎没有什么区别。
-
但要提一下,这个hello world应用程序需要1秒来处理1000个并行请求。 Quarkus的时间是6秒。
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());
}
}