Частичное чтение и запись данных с помощью Spring Batch - OutOfMemoryError: Превышен лимит накладных расходов GC - PullRequest
0 голосов
/ 21 сентября 2018

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

o.s.batch.core.step.AbstractStep -  Encountered an error executing step upload in job reviewsToYtBatchJob
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.mysql.jdbc.Buffer.<init>(Buffer.java:59)
at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1967)
at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3401)
at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:483)
at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3096)
at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2266)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1485)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:856)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2318)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
at org.springframework.batch.item.database.JdbcCursorItemReader.openCursor(JdbcCursorItemReader.java:126)

Мои вопросы:

  • Как получить кучупараметр размера?
  • Как извлечь данные частично?

Работает только при небольшом количестве данных.Я также пробовал это:

reader.setFetchSize(CHUNK_SIZE); //JdbcCursorItemReader
uploadStep.chunk(CHUNK_SIZE);  //SimpleStepBuilder

CHUNK_SIZE пробовал от 100 до 10000 Если я ограничу выбранные данные размером, который он работает, размер кучи не был превышен.

protected ItemReader<Review> reader() {
        JdbcCursorItemReader<Review> reader = new JdbcCursorItemReader<>();
        reader.setDataSource(dataScource);
        reader.setSql(
         //sql query
        );
        reader.setFetchSize(CHUNK_SIZE);
        reader.setRowMapper(
                (rs, rowNum) -> new Review(
                        rs.getLong("reviewId"),
                        //map data

                )
        );
        return reader;
    }

private ItemProcessor<Review, ReviewTo> processor() {
        return review -> new ReviewTo(
                //parameters
        );
    }
private ItemWriter<ReviewTo> writer() {
    return new ItemWriter<>(client);
}

private TaskletStep uploadStep() {
    SimpleStepBuilder<Review, ReviewTo> uploadStep = new SimpleStepBuilder<>(stepBuilderFactory.get("upload"));
    return uploadStep
            .chunk(CHUNK_SIZE)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .allowStartIfComplete(true)
            .build();
}

@Bean
public Job reviewsToYtBatchJob() {
    return jobBuilderFactory.get(JOB_NAME)
            .start(//generate table)
                    .build())
            .next(stepBuilderFactory.get("createTmpTable")
                    .tasklet(//step)
                    .build())
            .next(uploadStep())
            .next(stepBuilderFactory.get("moveTmpTableToDestination")
                    .tasklet(//step)
                    .build())
            .build();
}

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Недостаточно памяти.Работало с параметрами CHUNK_SIZE = 100000 и -Xmx4g.Был файл конфигурации с аргументами для виртуальной машины, где я мог увеличить размер кучи.

0 голосов
/ 21 сентября 2018

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

Как получить параметр размера кучи?

Хорошо, этот параметр - то, что вы передалиJVM с -Xms и -Xmx.См. Значения по умолчанию в документации вашей JVM.

Как извлекать данные частично?

Когда вы настраиваете этап, ориентированный на чанк, Spring Batch сделает это автоматически в соответствии сразмер куска вашего шага и выбор размера вашего JdbcCursorItemReader.Кстати, я вижу, вы устанавливаете одинаковое значение для этих двух параметров, что хорошо!Сопоставление fetchSize и chunkSize обычно приводит к лучшей производительности.

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

...