Есть ли лучший подход для сокращения времени выполнения долгого кварцевого задания? - PullRequest
0 голосов
/ 12 октября 2019

У меня есть задание cron, которое будет запускаться где-то ночью, которое получает большое количество productIds около 100 КБ из БД, и получает productInfo для всех из них от службы, которая требует около 700 мс для вызова API для1 productId.

CronJob

public class GetProducts extends QuartzJobBean {

    @Autowired
    private ProductClient productClient;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

        List<Long> ProductsIds = fetchAllProductIdsFromDb();

        Response<ProductClientResponse> response = null;

        for (Long productId : ProductsIds) {
            ProductClientRequestBody requestBody = new ProductClientRequestBody();
            requestBody.putIdInsideTheRequestBody(productId);
            response = productClient.getResult(requestBody).execute();

            if (response != null && response.isSuccessful()) {
                log.info("We have got successful response for {}", i);
            }
        }
    }
}

Здесь productClient является клиентом Retrofit службы. Так что технически эта работа займет 5 часов.

#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName=QuartzScheduler
org.quartz.scheduler.instanceId=AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=80
org.quartz.threadPool.threadPriority=5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.maxConnections=10
org.quartz.dataSource.myDS.validationQuery=select 0 from dual
org.quartz.scheduler.batchTriggerAcquisitionMaxCount =10
org.quartz.dataSource.myDS.URL=jdbc:mysql://127.0.0.1:3306/quartz
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=root

Это мой файл свойств кварца. Я хотел бы знать, есть ли лучший подход, чтобы получить ProductInfo для всех продуктов 100k.

Один подход

Я планирую 100 000 заданий для всех ProductIds. и хотя кварц, работающий в кластерной среде, будет планировать в соответствии с доступным экземпляром.

org.quartz.threadPool.threadCount = 80 - это свойство указывает, что в одном экземпляре службы не более80 потоков могут приступить к работе. Это так? И если у меня запущено 2 экземпляра, то одновременно может выполняться не менее 100-160 заданий. Я прав в своем подходе? что может значительно сократить время.

Есть ли какой-нибудь другой способ лучше, чем этот?

1 Ответ

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

Примечание: - Это для демонстрации подхода, который может дополнительно импровизировать код (я не тестировал код и могут быть синтаксические ошибки)

</p>

<p>public class ProductsJob extends QuartzJobBean {</p>

<pre><code>@Autowired
private ProductClient productClient;

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    List<Long> ProductsIds = fetchAllProductIdsFromDb();
    ProductsExecutor productsExecutor=new ProductsExecutor();
    productsExecutor.runTasks(ProductsIds);
}

}

открытый класс ProductsExecutor {

private int threadPoolSize=10;
private ExecutorService executorService;

public ProductsExecutor()
{
    executorService =Executors.newFixedThreadPool(threadPoolSize);
}

public void runTasks(List<Integer> productIds)
{
    //Loop and execute the task and wait for them it necessary
    ProductsWorker worker=new ProductsWorker();
    worker.setProductId(productId);
     executorService.invokeAll(worker);
}

}

открытый класс ProductsWorker реализует Runnable {

private int productId;@Override public void run () {ProductClientRequestBody requestBody = new ProductClientRequestBody ();requestBody.putIdInsideTheRequestBody (ProductID);response = productClient.getResult (requestBody) .execute ();if (response! = null && response.isSuccessful ()) {log.info («Мы получили успешный ответ для {}»);}} public void setProductId (int productId) {this.productId = productId;}

}

Не забудьте уничтожить службу-исполнитель, так как при каждом запуске кварца будет создаваться новая служба-исполнитель. Также вы можете добавить awaitTermination для всех представленных задач.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...