2015-04-24 3 views
1

Мы разрабатываем одно приложение, которое будет читать несколько файлов. & пишите несколько файлов, то есть один выходной файл для одного входного файла (имя выходного файла должно быть таким же, как и входной файл). MultiResourceItemReader может читать несколько файлов, но не одновременно, что является узким местом для нас. Spring-пакет обеспечивает поддержку многопоточности для этого, но снова многие потоки будут читать один и тот же файл & попробуйте написать его. Поскольку имя выходного файла должно быть таким же, как имя входного файла, мы также не можем использовать эту опцию.Чтение и запись нескольких файлов одновременно с использованием Spring-партии

Теперь я ищу еще одну возможность, если я могу создать 'n' потоков для чтения & напишите 'n' файлы. Но я не уверен, как интегрировать эту логику с использованием Spring Batch.

Благодарим за помощь.

ответ

1

Поскольку MultiResourceItemReader не отвечает вашим требованиям к производительности, вы можете более подробно ознакомиться с parallel processing, который вы уже упоминали, является желательным вариантом. Я не думаю, что многие потоки будут читать один и тот же файл и попытаться записать его при запуске многопоточного, если он настроен правильно.

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

Общий поток будет что-то вроде этого:

  1. Получить имена всех файлов, которые должны быть считаны в/выписал (через некоторый класс обслуживания) и сохранить их в контексте выполнения в реализация Partitioner.

    public class filePartitioner implements Partitioner { 
    
    @Override 
    public Map<String, ExecutionContext> partition(int gridSize) { 
        Map<String, Path> filesToProcess = this.service.getFilesToProcess(directory); // this is just sudo-ish code but maybe you inject the directory you'll be targeting into this class 
        Map<String, ExecutionContext> execCtxs = new HashMap<>(); 
        for(Entry<String, Path> entry : filesToProcess.entrySet()) { 
         ExecutionContext execCtx = new ExecutionContext(); 
         execCtx.put("file", entry.getValue()); 
         execCtxs.put(entry.getKey(), execCtx); 
        } 
    
        return execCtxs; 
    } 
    
    // injected 
    public void setServiceClass(ServiceClass service) { 
        this.service = service; 
    } 
    } 
    

    a. Для метода .getFilesToProcess() вам просто нужно что-то, что возвращает все файлы в указанном каталоге, потому что вам нужно знать, что должно быть прочитано, и имя файла, который должен быть записан. Очевидно, что существует несколько способов, чтобы идти об этом, таких как ...

    public Map<String, Path> getFilesToProcess(String directory) { 
        Map<String, Path> filesToProcess = new HashMap<String, Path>(); 
        File directoryFile = new File(directory); // where directory is where you intend to read from 
        this.generateFileList(filesToProcess, directoryFile, directory); 
    
    private void generateFileList(Map<String, Path> fileList, File node, String directory) { 
        // traverse directory and get files, adding to file list. 
    
        if(node.isFile()) { 
         String file = node.getAbsoluteFile().toString().substring(directory.length() + 1, node.toString().length()); 
         fileList.put(file, directory); 
    } 
    
        if(node.isDirectory()) { 
         String[] files = node.list(); 
         for(String filename : files) { 
          this.generateFileList(fileList, new File(node, filename), directory); 
         } 
        } 
    } 
    
  2. Вам нужно создать тасклет, который будет тянуть имена файлов из контекста исполнения и передать их в какой-то впрыскивается класс, который будет читать в файле и записывать его (могут потребоваться пользовательские ItemReaders и ItemWriters).

  3. Остальная часть работы будет в конфигурации, которая должна быть достаточно простой. Он находится в конфигурации Partitioner, где вы можете установить размер сетки, который может быть даже выполнен динамически с использованием SpEL, если вы действительно собираетесь создавать n потоков для n файлов. Я бы поставил на то, что фиксированное количество потоков, работающих в n файлах, продемонстрировало бы значительное улучшение производительности, но вы сможете определить это для себя.

Надеюсь, это поможет.

Смежные вопросы