2015-05-07 6 views
2

Это большое количество проблем с дизайном и кодом.Параллельная обработка файлов: какие рекомендуемые способы?

Use Case
- Учитывая большое количество файлов журналов в диапазоне (2МБ - 2 Гб), мне нужно, чтобы разобрать каждый из этих журналов и применить некоторую обработку, генерировать Java POJO.
- По этой причине давайте предположим, что у нас есть только файл журнала 1
- Кроме того, идея состоит в том, чтобы наилучшим образом использовать Систему. Доступны несколько ядер.

Альтернатива 1
- Открыть файл (синхронно), читать каждую строку, генерировать POJO сек

FileActor -> read each line -> List<POJO> 

Pros: простой для понимания
Cons: Последовательный процесс , не воспользовавшись несколькими ядрами в системе

Альтернатива 2
- Open File (синхронно), чтение N линии (N настраивается), проходит по разным акторам обрабатывать

            /LogLineProcessActor 1 
FileActor -> LogLineProcessRouter (with 10 Actors) -- LogLineProcessActor 2 
                \ LogLineProcessActor 10 

Доводы Некоторых распараллеливания, используя разные актеров для обработки части линий. Актеры будут использовать доступные ядра в системе
Против Still Серийных, потому что чтение файла последовательного способом

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

Просьба представить ценные мысли здесь

Большое спасибо

+0

Я думаю, что [ParallelStreams] (https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html) может быть подходящим для вашей проблемы. – Turing85

+0

Или даже https://storm.apache.org/, если вы постоянно получаете новые файлы и хотите действительно надежный конвейер. – Dathan

+0

Это решение должно быть установлено на клиентских машинах, поэтому я не уверен, что «Storm» выполним. – daydreamer

ответ

2

Почему бы не воспользоваться тем, что уже имеется, и использовать paralell поток материала, который поставляется с JDK 1.8? Я хотел бы начать с чем-то вроде этого, и посмотреть, как она выполняет:

Files.lines(Paths.get(/* path to a log file */)) 
    .parallel() // make the stream work paralell 
    .map(YourBean::new) // Or some mapping method to your bean class 
    .forEach(/* process here the beans*/); 

Вам может потребоваться некоторые хитрости с резьбой аккумулирования, потому что paralell() по умолчанию выполняется с использованием ForkJoinPool.commonPool(), и вы не можете настроить его для достижения максимальная производительность, но люди, похоже, тоже обходят обходные пути, some stuff about the topic here.

0

Альтернатива 2 выглядит хорошо. Я бы просто изменил ситуацию. Прочтите самый большой фрагмент файла, который вы можете. IO будет проблемой, если вы сделаете это в небольших очередях. Поскольку есть несколько файлов, я бы создал актера, чтобы получить имя файла, прочитав конкретную папку. Затем он отправит путь к каждому файлу в LogLineReader. Он будет читать большой фрагмент файла.И, наконец, он отправит каждую строку в LogLineProcessActor. Имейте в виду, что они могут обрабатывать линии не по порядку. Если это не проблема, они будут держать ваш CPU занятым.

Если вы считаете себя предприимчивым, вы также можете попробовать новый akka stream 1.0.

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