Недавно на работе мне нужно было просмотреть наши архивные файлы и предоставить результаты к концу дня. Вот параметры запроса:
- Архивные файлы зашифрованы и хранятся в HDFS (не спрашивайте, почему мы храним их в HDFS).
- Файлы различаются по размеру от 3 до 9 ГБ.
- Общее количество файлов для поиска было 300+
- Расшифровка каждого файла занимает от 1 до 2 минут.
В прошлом были запросы на поиск в одном архивном файле. В этих случаях мы будем копировать файл из HDFS на сервер. Затем запустите сценарий оболочки, чтобы расшифровать файл и выполнить поиск. Программа расшифровки требует 2 аргумента: зашифрованный файл и файл для записи расшифрованных данных. Это означает, что расшифрованный и зашифрованный файл находятся на диске одновременно.
При средней скорости 1,5 минуты для расшифровки одного файла для 300 файлов требовалось 450 минут (7,5 часов). Чтобы добавить к моей дилемме, не было достаточно времени, чтобы написать собственный RecordReader . Единственным решением было бы передавать файлы параллельно. Но есть 2 проблемы с этим подходом:
- На сервере недостаточно места для 20 (10 зашифрованных и 10 расшифрованных) файлов одновременно.
- Код дешифрования выполняет чтение из стандартного ввода или запись в стандартный вывод.
Что делать? Используйте именованные каналы, конечно!
Ускоренный курс по именованным каналам
Трубы используются для составления узконаправленных программ для решения более широких задач. Например :
cat someFile.txt | awk -F "|" '{print $5}' | cut -d ':' f2
В этом примере мы используем анонимные каналы (обозначаемые символом «|»). Трубы, используемые в командной строке или в сценариях, живут только в течение текущего процесса. Именованные каналы похожи с этими исключениями:
- Вы создаете именованные каналы с помощью команды
mkfifo name-of-pipe. - Может использоваться повторно несколькими процессами.
- Namped трубы сохраняются, пока не будут удалены с помощью команды
rm name-of-pipe. - Существуют в файловой системе и отображаются в виде файлов для других процессов.
- Разрешить межпроцессное взаимодействие.
Вот пример создания именованного канала и как он выглядит в файловой системе:
new-host-2:~ bbejeck$ mkfifo pipe1 new-host-2:~ bbejeck$ ls -l pipe1 prw-r--r-- 1 bbejeck staff 0 Aug 16 21:28 pipe1
Обратите внимание, что именованный канал отображается в lsрезультатах, и первый столбец слева — это p. Если вам больше не нужен именованный канал, просто удалите его, как файл с командой rm pipe1.
Мое решение с именованными трубами
Сначала я создал файл, состоящий из путей к архивам. Затем скрипт перебрал файл и запустил 10 процессов дешифрования / поиска параллельно. После запуска 10 процессов сценарий будет ожидать завершения всех 10 процессов, прежде чем запускать другой пакет.
count=0
while read fileName; do
if [[ $((++count)) -eq 10 ]]; then
count = 0
wait
fi
#backgrounded process
processFile $fileName &
done < inputFileNames.txt
Вот код для processFileфункции.
function processFile {
encryptedFile=$(basename ${1})
decryptedFile=${encryptedFile%.enc}
mkfifo ${encryptedFile}
mkfifo ${decryptedFile}
hdfs dfs -cat ${1} > ${encryptedFile} &
cat ${decryptedFile} | awk '{ if ( $5 == someValue) print $0}' &
/somepath/decryptFile.sh ${encryptedFile} ${decryptedFile}
rm ${encryptedFile} ${decryptedFile}
}
Хотя processFileфункция проста, есть несколько шагов, которые мы должны объяснить:
- Строка 2: создайте переменную с базовым именем зашифрованного файла из полного пути.
- Строка 3: создайте переменную имени зашифрованного файла за вычетом
.encрасширения файла. - Строки 5,6: Создание именованных каналов для зашифрованного и расшифрованного файла.
- Строка 8: поток зашифрованный файл из HDFS и перенаправить на зашифрованный именованный канал и фоновый процесс.
- Строка 9: Запустите
catкоманду для расшифрованного файла. Затем передайте результатыawkи найдите нужную информацию. Это тоже фоновое. - Строка 11: вызов сценария дешифрования с необходимыми параметрами файла.
- Строка 12: после расшифровки и поиска файла удалите именованные каналы.
Вывод
Использование именованных каналов позволило мне расшифровать и найти более 300 файлов примерно за 1,5 часа. Я также избежал проблемы с пространством, так как мне никогда не приходилось записывать файл на диск. Хотя именованные каналы не нужны каждый день, они являются полезным инструментом в вашем арсенале.