Как узнать размер очереди исполнителя в реальном времени - PullRequest
2 голосов
/ 16 октября 2019

Предполагается, что у меня есть это application.java

@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(50);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(5000);
        executor.setThreadNamePrefix("sm-async-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}

Моя цель - создать предупреждение, если текущий размер очереди в реальном времени асинхронного исполнителя составляет 80% или почти предел. Я думаю, что мы можем получить значение от executor.getThreadPoolExecutor().getQueue().size();. В настоящее время я застрял на том, как этого добиться

Ответы [ 4 ]

2 голосов
/ 16 октября 2019
@Controller
public class QueueMonitorController {

    @Autowired
    private Executor executor;

    @RequestMapping(value = "/queuesize", method = RequestMethod.GET)
    public int queueSize() {
        ThreadPoolExecutor tpe = (ThreadPoolExecutor)executor;
        return tpe.getThreadPoolExecutor().getQueue().size();
    }
}

Если вы можете предоставить боб как ThreadPoolExecutor, то вам даже не нужен состав. Внутренняя реализация size() в LinkedBlockingQueue (которую использует ThreadPoolExecutor): AtomicInteger.get().

Так что нет необходимости проявлять креативность и создавать свои собственные механизмы, все это встроено. Основан на Spring 4.2, но не должен слишком сильно зависеть от версии.


Таким образом, основной целью является мониторинг очереди и отправка оповещения, когда очередь заполнена на 80%. Это не должно входить в ваш код, который отвечает за работу вашей бизнес-логики. Вы не должны делать хаки там, чтобы объяснить нехватку ресурсов. Если идея заключается в том, что вы должны ограничивать пользователей, когда очередь упакована, есть гораздо лучшие способы справиться с ними.

Поскольку идея состоит в том, чтобы сделать «легкий мониторинг», то есть нет попытки обработать В случае, когда очередь заполнена на 80%, решение для опроса будет достаточно легким. Учитывая, что исполнитель может быть легко введен в отдельный Controller, он даже не испортит ваш «настоящий» код.

1 голос
/ 16 октября 2019

Поскольку ThreadPoolTaskExecutor не предоставляет API, вы можете получить используемую им очередь. Тем не менее, вы можете расширить ThreadPoolTaskExecutor и создать CustomThreadPoolTaskExecutor переопределить createQueue.

public class CustomThreadPoolTaskExecutor extends ThreadPoolTaskExecutor{

    private BlockingQueue<Runnable> queue;

    @Override
    protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
        queue = super.createQueue(queueCapacity);
        return queue;
    }

    public BlockingQueue<Runnable> getQueue(){
      return queue;
    }
}

Теперь вы можете создать asyncExecutor, как показано ниже:

@Bean
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();
    //set other properties
    executor.initialize();
    return executor;
}

У вашего CustomThreadPoolTaskExecutor исполнителя есть открытый метод getQueue, и вы можете использовать его для получения очереди.

0 голосов
/ 16 октября 2019

Сделать это в реальном времени, как вы просите, не так просто. Вам нужно будет украсить методы BlockingQueue, чтобы вы могли добавить код для немедленного выполнения при изменении содержимого очереди.

Затем вы можете предоставить свою очередь для Spring * ThreadPoolTaskExecutor следующим образом:

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
  @Override
  protected BlockingQueue<Runnable> createQueue(int queueCapacity) {

    // create and return your instance of blocking queue here
  }
};
0 голосов
/ 16 октября 2019

Я не знаю, откуда у вас ThreadPoolTaskExecutor тип класса исполнителя. Но в Java вы можете набрать ThreadPoolExecutor и получить очередь и ее размер, как показано ниже:

ThreadPoolExecutor executorService =  (ThreadPoolExecutor )Executors.newCachedThreadPool();
        executorService.getQueue().size()
...