отже, онлайновий щоденник tivasyk@home перенесено з гуглівського blogger’а на власний сервер, і переведено на текстові файли markdown, які зберігаються у власному сховищі owncloud і з яких автоматично генерується статичний веб-сайт за допомогою двигунця jekyll, а traefik забезпечує шифрування ssl/tls з сертифікатом let’s encrypt. лишається одна проблема, яка мене бентежить: високе завантаження процесора контейнером jekyll.
проблема
поки я лінуюся переписати до ума свій скрипт для моніторингу, накидав на колінці ось таке для спостереження за контейнерами, завантаженням процесора і журналом контейнера:
#!/usr/bin/env bash
# CONSOLE WIDTH?
WIDTH=$(tput cols)
# UPTIME
printf "UPTIME\n"
uptime
# PROCESSES
printf "\nCPU USAGE\n"
ps -e -o pid= -o %cpu= -o %mem= -o command= | sort -n -r -k 2 | head -n 3 | cut -c -$WIDTH
# CONTAINERS
printf "\n"
docker ps --format="table {{.Names}}\t{{.Status}}\t{{.Command}}\t{{.Ports}}" | cut -c -$WIDTH
# LOGS
if [[ "$1" != "" ]]; then
printf "\nLOGS\n"
docker logs $1 --tail 10 | cut -c -$WIDTH
fi
і що ж я бачу? ruby в контейнері jekyll постійно завантажує одне ядро процесора на 80-100% (див. ілюстрацію). решта системи й контейнери поводяться добре, і якщо я «приб’ю» jekyll, завантаження процесора падає до 2-3%!
перша гіпотеза: веб-сервер?
спершу я гадав, що проблему створює веб-сервер jekyll, написаний на ruby, — тому я додав контейнер з легким веб-сервером lighttpd і відключив веб-сервер jekyll: запускаю в режимі build замість serve. виявилося, що це зменшує навантаження в кращому випадку на 5%, але не вирішує проблеми.
друга гіпотеза: відслідковування змін?
наступна гіпотеза стосувалася відслідковування змін в теці з дописами: стандартно контейнер jekyll використовує опцію --force-polling
, яка змушує двигунець перезапускати генерацію щоразу, коли вміст теки з дописами змінюється. потенційно це джерело підвищеного навантаження на процесор, тож я спробував поміняти режим на --wait
, а також додав опцію --incremental
, котра змушує jekyll обробляти лише змінені файли замість щоразу перебирати всі дописи.
перша зміна (--wait
) ніяк не вплинула на завантаження; друга (--incremental
) — сильно скоротила час генерації сайту, з 200 секунд до 30 секунд з хвостиком. оскільки я копіюю змінені файли за допомогою rsync раз на п’ять хвилин — це мало би вирішити проблему завантаження, адже jekyll «крутив» би процесор до 80% упродовж 30 секунд, а тоді «засинав» би до наступного поновлення.
але мій «наколінний» скрипт для моніторингу показує, що, по-перше, jekyll закінчує генерувати сайт — і майже одразу починає наступний цикл, попри те, що я не додаю нових дописів на owncloud! а по-друге, насправді генерація сайту триває значно більше за 30 секунд…
третя гіпотеза: owncloud та rsync?
чи можливо, що owncloud періодично дописує якісь атрибути до тек чи окремих файлів блогу, rsync бачить це як зміни й що п’ять хвилин переписує вміст теки з owncloud до jekyll, а jekyll реагує на ці «зміни» й кидається переписувати сайт? для перевірки я встановив пакунок inotify-tools
заради утиліти inotifywatch
, котра вміє відслідковувати зміни файлів:
inotifywatch -m --format "%T %e %w%f" --timeftm "%Y-%m-%d, %H:%M" ~/jekyll/blog/_posts
дивно, але inotifywatch не детектує жодних змін у файлах, окрім створення тимчасових копій кожного допису (імена починаються з крапки) — але ls -lt
чітко показує, що всі файли (принаймні їхні атрибути) перезаписано що п’ять хвилин! вочевидячки, це таки робота rsync…
детальний опис алгоритму роботи rsync натякає, що файли дрежела та цілі порівнюються за часом та розміром; отже, якщо rsync не пересилає час створення в переліку файлів джерела (дякую disfinder за підказку в коментарях)… тоді навіть якщо дельта порожня (змінена частина файлу) — в теці цілі rsync все-одно збирає тимчасовий файл (він буде ідентичний тому, що там вже є) і (див. алгоритм) заміняє ним поточний файл?! посібник (man rsync
) прямо радить уникати цього, вживаючи опцію -t
, про яку я й забув, налаштовуючи копіювання.
отже, перевірка: додаю опцію -t
до свого скрипта copy2blog
і споглядаю вивід мого монітора контейнерів…
rtfm, як завжди!
…і бачу, що ruby так само крутить процесор до 70-80%, майже як і раніше? але рядок uptime
і вивід top
показують, що все нормалізувалося! як так?!
відповідь: rtfm, ламеряко! ps
має проблеми особливості з визначенням використання процесора, і про це білим по чорному написано в посібнику: він обраховує середнє використання за увесь час роботи програми!
в підсумку: однієї опції rsync бракувало, через що jekyll щоразу кидався перебудовувати весь сайт попри інструкцію робити лише інкрементальні поновлення. проблему вирішено.