Піднімаємо сайт: "невідкладна" поки спить адмін


Дуже погано, коли сайт падає. Набагато гірше, коли він падає через незрозумілу причину. Іноді на встановлення причини збою може знадобитися тривалий час, якщо весь цей час сайт "лежатиме" адміністратор може просто звільнити. На щастя, є рішення, що дозволяє трохи скрасити "гіркоту падіння" і воно буде описано у цій статті.

Не панацея, а милиця

Автор цієї статті на своїй практиці зіткнувся з нестабільною роботою сайту (віртуальний Linux-сервер, CMS Magento). Причому півроку сайт працював як швейцарський годинник, а потім почалися незрозумілі падіння.

Сутність рішення в наступному: потрібно налаштувати/написати самому засіб моніторингу працездатності сайту. Якщо сайт "упав", цей засіб буде перезапускати сервіси Apache та MySQL (або тільки Apache – все залежить від специфіки сайту та причини збою). Рішення, звичайно ж, тимчасове. Потрібно знайти і усунути причину падіння, зате такий "милиця" дозволяє швидко відновити працездатність сайту: керівництво навіть не помітить збій. Що ж стосується звичайних користувачів, то навіть якщо хтось і отримає 550 помилку, а через хвилину сайт вже буде працювати, навряд чи хтось особливо скаржитися.

Перевіряти працездатність сайту можна двома способами: або намагатися отримати реальний файл (можна для цього створити порожній файл докорінно, важливо отримати 200-у відповідь від сервера) або моніторити наявність сервісів apache/mysql в пам'яті. Другий спосіб не захищає від ситуації, коли сервіси "підвисли" – у пам'яті вони є, але насправді сайт "лежать". Перший спосіб не дозволяє переконатися у працездатності MySQL: файл веб-сервер може і віддати, а база даних може не працювати.

Перевірка працездатності веб-сервера

Найпростіше перевірити працездатність веб-сервера шляхом звернення до його головної сторінки: якщо отримано відповідь 200, значить із сервером все добре. Bash-сценарій виглядатиме так:

#!/bin/bash

if curl -s --head --request GET https://site.name | grep "200 OK" > /dev/null; then
   echo "Site is UP"
else
   echo "site is DOWN, restarting Apache"
   /usr/sbin/service apache2 restart
fi

Виклик сценарію потрібно розмістити в розкладі cron. Періодичність залежить від частоти падіння сервера - якщо сервер збоїть іноді, можна раз на 5-10 хвилин, якщо сайт "лежить" часто - раз на хвилину. Так, це створить додаткове навантаження на сервер, зате забезпечить його перезапуск протягом однієї хвилини.

Перевірка працездатності MySQL

Напишемо невеликий PHP-сценарій, що підключається до БД і повертає 1, якщо з'єднання вдалося і 0, якщо з'єднання не працює. Власне код цього сценарію дуже простий:


include "config.php"; // тут параметри доступу до БД

$mysqli = new mysqli($DBHOST, $DBUSER, $DBPASSWD, $DBNAME);

if ($ mysqli->connect_errno) {
echo "0";
}
else "1"; // connect ok

Потім створюється bash-сценарій подібний до цього:

#!/bin/bash
RESULT=$(/usr/bin/php test-mysql.php)
if [$RESULT -eq 0]; then
echo "Restarting MySQL"
/etc/init.d/mysqld restart
fi

Як і у випадку з першим нашим bash-сценарієм, виклик цього сценарію потрібно помістити в розклад планувальника. Можна об'єднати ці два bash-сценарії в один і викликати все одразу.

Якщо падають процеси

Якщо процеси не виснуть, а "падають", тобто після збою взагалі немає процесів Apache/MySQL у таблиці процесів, тоді допоможе наступний сценарій:

#!/bin/bash
RESTART="/etc/init.d/apache2 restart"
PGREP="/usr/bin/pgrep"
HTTPD="apache2"
$PGREP ${HTTPD}
if [$? -ne 0]; then
$RESTART
date >> /var/log/srvmon.log
echo "Apache restarted" >> /var/log/srvmon.log
fi

RESTARTM="/etc/init.d/mysql restart"
MYSQLD="mysqld"
$PGREP ${MYSQLD}
if [$? -ne 0]; then
$RESTART
$RESTARTM
date >> /var/log/srvmon.log
echo "Services restarted" > /var/log/srvmon.log
fi

Він не тільки перезапускає "сервіси, що впали", але й веде невеликий лог - записує час, коли сервіси були перезапущені.

Monit: якщо немає таланту програміста

Все наведене раніше можна зробити за допомогою сервісу monit. Його завдання – моніторинг працездатності сервера. Якщо щось не так, то monit може перезапустити ту чи іншу службу.

В Інтернеті є безліч статей, присвячених monit, до того ж у нього дуже хороша документація. Тому не хочеться плагіатити – нічого нового на тему monit не напишеш. Натомість наведу реальний конфіг моніторингу Apache з одного з адміністрованих автором цієї статті серверів:

check process apache with pidfile /var/run/apache2.pid
    group www
    group apache
    start program = "/etc/init.d/apache2 start"
    stop program = "/etc/init.d/apache2 stop"
    # Якщо завантаження cpu > 90% 5 циклів, то перезапустити процес.
    if cpu > 90% for 5 cycles then restart
    # якщо не вдається отримати файл server-status, перезапустити
    if failed host localhost port 80 with protocol http and request "/server-status" with timeout 25 seconds for 4 times within 5 cycles then restart
    depend apache_bin
    depend apache_rc

  check file apache_bin with path /usr/sbin/apache2
    group apache
    include /etc/monit/templates/rootbin

  check file apache_rc with path /etc/init.d/apache2
    group apache
    include /etc/monit/templates/rootbin
Конфігурація monit, думаю, зрозуміла навіть новачкові. На конкретному сервері була проблема з великим завантаженням процесора, після піку завантаження сервер падав. Тому було додано дві перевірки: якщо завантаження процесора вище 90%, сервіс перезапускався і якщо сервер вже впав (не вдається одержати файл), то сервіс також перезапускався.