ExecutorService медленно и иногда зависает - PullRequest
0 голосов
/ 01 августа 2020

Я вызываю API множественного отдыха и для этого использую ExecutorService для параллельной обработки. Потребитель обращался к моему приложению более 10 раз в секунду, и я заметил, что ExecutorService очень медленно реагирует. Я развернул свое приложение на kubernetes с помощью веб-сервера tomcat. ниже мой код, не уверен, что вызывает его замедление.

   ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(100);

            Collection tasks = new ArrayList();
  for( String str: datalist){
 tasks.add(new MyThreadPool(str)); // MyThreadPool internally calls the REST API using Google HttpRequest.
}
 List<Future<BasePolicy>> futures = null;
            try {
                long startProcessingTime = System.currentTimeMillis();
                futures = WORKER_THREAD_POOL.invokeAll(tasks);
                WORKER_THREAD_POOL.shutdown();

                if (!WORKER_THREAD_POOL.awaitTermination(60000, TimeUnit.SECONDS)) {
                    WORKER_THREAD_POOL.shutdownNow();
                }

                long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
                log.info("total time to complete the thread pool- " + totalProcessingTime);
            } catch (InterruptedException e) {
                log.error("error occured during ASYNC process ");
                e.printStackTrace();
            }
            log.info("Finished Waiting All threads completed ");
            for (Future<Data> mFuture : futures) {
               // my logic 
            }

Ответы [ 2 ]

2 голосов
/ 01 августа 2020

, и я заметил, что ExecutorService очень медленно реагирует.

ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(100);

Начнем с вопроса: сколько ядер у вашей машины?
Для, newFixedThreadPool, рекомендуется начинать с такого количества потоков, которое соответствует количеству ядер на вашем компьютере (если задачи выполняются долго). При значении 100 ваш ЦП будет занят планированием и переключением контекста . Вдобавок ко всему, поскольку это newFixedThreadPool, очень много потоков останется в пуле даже при меньшей нагрузке - это не поможет ЦП.

Как предложено в Эффективно Java, newCachedThreadPool обычно приносит пользу . Здесь больше относится к пулам потоков.

Если вы ожидаете действительно большой нагрузки, я думаю, что развертывание приложений на нескольких серверах было бы разумным решением (это зависит от емкости вашего единственного сервера). Потоки не помогут и в конечном итоге могут замедлить работу вашего приложения.

0 голосов
/ 01 августа 2020

Когда вы развертываете приложение в кубернетах, если вы не укажете требования memory и cpu, тогда планировщик кубернетов планирует поместить модуль в узел на основе максимальных усилий, что может привести к истощению и даже выселению модуля.

Вы можете помочь планировщику принять лучшее решение по планированию, указав требования memory и cpu, как показано ниже

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    env:
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m" 

Это гарантирует, что модуль будет запланирован на узле, который может удовлетворить требование запуска с 64Mi памяти, 250m cpu и позволить ему увеличиваться до 128Mi памяти, 500m cpu.

...