Проблема теста производительности веб-клиента Vertx

Я пытаюсь написать тест производительности, чтобы проверить производительность моего API. Я использую веб-клиент vertx для получения тестов. Веб-клиент не вызывается для начальных запросов, а для всех других запросов он также показывает гораздо больше времени, чем на сервере. Сервер, на который я обращаюсь, работает на другом компьютере и не работает на локальном хосте. Я использую vertx 3.9.2. Посмотрите на фрагмент кода ниже и предположите, что я делаю неправильно.

@Slf4j
public class HttpTest {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory");
        InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE);
        Vertx vertx = Vertx.vertx(new VertxOptions()
                .setPreferNativeTransport(true)
                .setEventLoopPoolSize(2 * CpuCoreSensor.availableProcessors())
                .setWarningExceptionTime(TimeUnit.SECONDS.toNanos(2)));

        ...

        for (int i = 0; i < numberOfThreads; i++) { // numberOfThreads = 20, runDurationInMinutes=2
            Future<Integer> testRequest = ((ExecutorService) executor).submit(new TestRequests(successfulRequestList, failedRequestList, url, System.currentTimeMillis() + (runDurationInMinutes * 60 * 1000), vertx));
            futureList.add(testRequest);
            Thread.sleep(1 * 100);
        }

        ...
}

public class TestRequests implements Callable<Integer> {

    private final List<Integer> successfulRequestList;
    private final List<Integer> failedRequestList;
    private final String url;
    private WebClient webClient;
    private final long stopTime;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    private boolean flag = true;

    public TestRequests(List<Integer> successfulRequestList, List<Integer> failedRequestList, String url, long stopTime, Vertx vertx) {
        this.successfulRequestList = successfulRequestList;
        this.failedRequestList = failedRequestList;
        this.url = url;
        this.stopTime = stopTime;
        WebClientOptions webClientOptions = new WebClientOptions().setUseAlpn(true).setSslEngineOptions(new OpenSSLEngineOptions()).setKeepAlive(true).setSsl(true).setLogActivity(false);
        webClient = WebClient.create(vertx, webClientOptions);
        this.webClient = webClient;
    }

    @Override
    public Integer call() throws Exception {
        final String requestBody = "... Some String ...";
        try {
            while (!Thread.currentThread().isInterrupted() && System.currentTimeMillis() < stopTime) {
                long currentTime = System.currentTimeMillis();
                try {
                    log.info("Sending request");
                    webClient
                            .postAbs("https://paceoffers-dev.test.com/graphql")
                            .ssl(true)
                            .putHeader("Trace_Id", "gt1")
                            .putHeader("Span_Id", UUID.randomUUID().toString())
                            .putHeader("Authorization", UUID.randomUUID().toString())
                            .putHeader("X-TEST-API-KEY", UUID.randomUUID().toString())
                            .putHeader("validate_hmac", "false")
                            .putHeader("Content-Type", "application/json")
                            .rxSendBuffer(Buffer.buffer(requestBody))
                            .subscribe(
                                    result -> {
                                        if (result != null && result.statusCode() == 200) {
                                            log.info("x-response-time: {} timeTaken: {}ms", result.getHeader("x-response-time"), System.currentTimeMillis() - currentTime);
                                            successfulRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                                        } else {
                                            log.error("statusCode: {} timeTaken: {}ms", result.statusCode(), System.currentTimeMillis() - currentTime);
                                            failedRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                                        }
                                    },
                                    error -> {
                                        log.error("Uncaught exception", error);
                                    }
                            ).dispose();
                    //log.info("Completed sending request");
                } catch (Exception e) {
                    if (e instanceof InterruptedException || Thread.interrupted()) {
                        return null;
                    }
                    e.printStackTrace();
                    failedRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                }
            }
        } catch (
                Exception e) {
            if (e instanceof InterruptedException) {
                return null;
            }
        }
        return null;
    }

---- ОБНОВИТЬ ----

Я изменил код, чтобы его можно было запускать как отдельное приложение. Я использую рабочий поток vertx. Проблема все еще существует.

Это автономный исполняемый код.

import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.internal.logging.Slf4JLoggerFactory;
import io.vertx.core.VertxOptions;
import io.vertx.core.impl.cpu.CpuCoreSensor;
import io.vertx.core.net.OpenSSLEngineOptions;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.core.WorkerExecutor;
import io.vertx.reactivex.core.buffer.Buffer;
import io.vertx.reactivex.ext.web.client.HttpResponse;
import io.vertx.reactivex.ext.web.client.WebClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.stat.StatUtils;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpTest {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory");
        System.setProperty("vertx.disableDnsResolver", Boolean.TRUE.toString());
        InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE);
        Vertx vertx = Vertx.vertx(new VertxOptions()
                .setPreferNativeTransport(true)
                .setEventLoopPoolSize(2 * CpuCoreSensor.availableProcessors())
                .setWarningExceptionTime(TimeUnit.SECONDS.toNanos(2)));
        log.info("vertx.isNativeTransportEnabled(): " + vertx.isNativeTransportEnabled());
        if (args.length < 3) {
            log.info("Argument 1(Number of Threads) - Integer, Argument 2(Test run duration in minutes) - Integer, Argument 3(The HTTPS POST url): String");
            System.exit(1);
        }
        int numberOfThreads = Integer.valueOf(args[0]);
        int runDurationInMinutes = Integer.valueOf(args[1]);
        String url = args[2];
        List<Integer> successfulRequestList = new Vector<Integer>();
        List<Integer> failedRequestList = new Vector<Integer>();
        CountDownLatch countDownLatch = new CountDownLatch(1);
        WorkerExecutor sharedWorkerExecutor = vertx.createSharedWorkerExecutor("vertx-worker", numberOfThreads, runDurationInMinutes * 60 + 5, TimeUnit.SECONDS);
        WebClientOptions webClientOptions = new WebClientOptions().setUseAlpn(true).setSslEngineOptions(new OpenSSLEngineOptions()).setKeepAlive(true).setIdleTimeout(60).setIdleTimeoutUnit(TimeUnit.SECONDS).setSsl(true).setTcpKeepAlive(true).setLogActivity(false);
        if (vertx.isNativeTransportEnabled()) {
            webClientOptions.setTcpCork(true).setTcpNoDelay(true).setTcpQuickAck(true);
        }
        WebClient webClient = WebClient.create(vertx, webClientOptions);
        final long startTime = System.currentTimeMillis();
        for (int i = 0; i < numberOfThreads; i++) {
            sharedWorkerExecutor.executeBlocking(f -> {

                log.info("Starting");
                final long stopTime = System.currentTimeMillis() + (runDurationInMinutes * 60 * 1000);
                final String requestBody = "{ \"query\": \"query($effts: Instant!, $planId: String!){ getOfferDetailsByPlanIdentifierAndEffectiveDate(effective_timestamp: $effts, plan_identifier: $planId) { name legal_names { value language } effective_timestamp end_timestamp jurisdiction { category name } category sub_category is_arrangement type features { identifier name configurations { identifier name duration { unit value } values { jurisdiction { category name } values } } terms { identifier name duration { unit value } values } } } } \", \"variables\": {\"effts\": \"2021-06-22T08:00:00.00Z\", \"planId\": \"P68\"}  }";
                while (!Thread.currentThread().isInterrupted() && System.currentTimeMillis() < stopTime) {
                    final long currentTime = System.currentTimeMillis();
                    try {
                        HttpResponse<io.vertx.reactivex.core.buffer.Buffer> result = webClient
                                .postAbs(url)
                                .ssl(true)
                                .putHeader("Trace_Id", "gt1")
                                .putHeader("Span_Id", UUID.randomUUID().toString())
                                .putHeader("Authorization", UUID.randomUUID().toString())
                                .putHeader("X-TEST-API-KEY", UUID.randomUUID().toString())
                                .putHeader("validate_hmac", "false")
                                .putHeader("Content-Type", "application/json")
                                .rxSendBuffer(Buffer.buffer(requestBody))
                                .map(resultVar -> {
                                    log.info("Time taken: " + (System.currentTimeMillis() - currentTime));
                                    return resultVar;
                                })
                                .blockingGet();
                        if (result != null && result.statusCode() == 200) {
                            log.info("x-response-time: {} timeTaken: {}ms", result.getHeader("x-response-time"), System.currentTimeMillis() - currentTime);
                            successfulRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                        } else {
                            log.error("statusCode: {} timeTaken: {}ms", result.statusCode(), System.currentTimeMillis() - currentTime);
                            failedRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                        }
                    } catch (Exception e) {
                        if (e instanceof InterruptedException || (e instanceof  RuntimeException && e.getCause() != null && e.getCause() instanceof InterruptedException) ||Thread.interrupted()) {
                            // Do nothing
                        } else {
                            log.error("Uncaught Exception", e);
                            failedRequestList.add(Integer.valueOf(Long.toString(System.currentTimeMillis() - currentTime)));
                        }
                    }

                }
                f.complete(Thread.currentThread().getName());
            }, handler -> {
                log.info("Completed processing for: {}", handler.result().toString());
            });
        }
        log.info("All users ramped up");
        try {
            log.info("Sleeping for " + runDurationInMinutes + " minute");
            countDownLatch.await(runDurationInMinutes, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("Shutting down the executor");
        sharedWorkerExecutor.close();
        vertx.close();
        final long endTime = System.currentTimeMillis();
        log.info("Sleeping for 5 seconds.....");
        Thread.sleep(5 * 1000);
        synchronized (successfulRequestList) {
            final int successfulRequest = successfulRequestList.size();
            log.info("Total Successful Requests: " + successfulRequest);
            int failedRequest = 0;
            synchronized (failedRequestList) {
                failedRequest = failedRequestList.size();
                log.info("Total Failed Requests: " + failedRequest);
            }
            double[] doubleOfInt = successfulRequestList.parallelStream().mapToDouble(i -> i).toArray();
            Arrays.sort(doubleOfInt);
            for (int i = 5; i <= 100; i = i + 5) {
                if (i == 100) {
                    log.info("Statistics | " + "99" + "%: " + StatUtils.percentile(doubleOfInt, 99));
                    log.info("Statistics | " + "99.1" + "%: " + StatUtils.percentile(doubleOfInt, 99.1));
                    log.info("Statistics | " + "99.2" + "%: " + StatUtils.percentile(doubleOfInt, 99.2));
                    log.info("Statistics | " + "99.3" + "%: " + StatUtils.percentile(doubleOfInt, 99.3));
                    log.info("Statistics | " + "99.4" + "%: " + StatUtils.percentile(doubleOfInt, 99.4));
                    log.info("Statistics | " + "99.5" + "%: " + StatUtils.percentile(doubleOfInt, 99.5));
                    log.info("Statistics | " + "99.6" + "%: " + StatUtils.percentile(doubleOfInt, 99.6));
                    log.info("Statistics | " + "99.7" + "%: " + StatUtils.percentile(doubleOfInt, 99.7));
                    log.info("Statistics | " + "99.8" + "%: " + StatUtils.percentile(doubleOfInt, 99.8));
                    log.info("Statistics | " + "99.9" + "%: " + StatUtils.percentile(doubleOfInt, 99.9));
                    log.info("Statistics | " + "99.99" + "%: " + StatUtils.percentile(doubleOfInt, 99.99));
                    log.info("Statistics | " + "99.999" + "%: " + StatUtils.percentile(doubleOfInt, 99.999));
                }
                log.info("Statistics | " + i + "%: " + StatUtils.percentile(doubleOfInt, i));

            }
            log.info("Throughput | " + (successfulRequest + failedRequest) / ((endTime - startTime) / 1000) + " tps");
            doubleOfInt = null;
            successfulRequestList.clear();
            failedRequestList.clear();
        }
    }
}

0 ответов

Другие вопросы по тегам