Сервис мониторинга доступности сайтов своими руками

Сервис мониторинга доступности сайтов своими руками

@low_digital

Начну, как всегда, из далека. Мониторинг доступности – вещь обязательная для любого владельца сайта/системного администратора/студии. Крайне важно вовремя реагировать на сбои в работе и кибератаки.

Кучу лет назад, я воспользовался первым попавшимся сервисом, который позволял осуществлять мониторинг бесплатно – это был Pingdom. Ограничения в 1 бесплатный аккаунт легко обходились алиасами почты (т.е. при регистрации я указываю разные ящики, но уведомления приходят все равно на мою основную почту) и публичной статистикой, где можно посмотреть скорость загрузки сайта и графики аптайма (просто сохраняешь публичные ссылки и периодически открываешь папку этих сохраненных ссылок для проверки).

Позже, Pingdom изменили ценовую политику и отказались от бесплатных тарифов – пришлось искать альтернативу. К тому моменту у меня у меня скопилось более 20 сайтов для мониторинга (при этом я мониторил не все сайты, а лишь те, которые находятся на разных серверах, т.к. основная моя проблема была в падающем MySQL при высокой нагрузке). Тарифы разных сервисов примерно одинаковые (10 сайтов / 50 сайтов / много сайтов), разница лишь в цене. Средний ценник за пакет из 50 сайтов на мониторинге - $50/мес., что довольно дорого, ведь клиенты (по крайней мере мои) не понимают зачем им этот мониторинг и не готовы платить за него.

В поисках самого бюджетного варианта, я наткнулся на сервис UpTimeRobot за $8/мес. и пользовался им последние 2 года. Но последнее время он всё чаще и чаще меня начал напрягать ложными срабатываниями, прилетает уведомление «САЙТ СДОХ», открываю, проверяю – всё нормально. Как оказалось, это работает и в обратную сторону – последнюю неделю я занимаюсь оптимизацией расходов на нашу ИТ-инфраструктуру (об этом тоже будет отдельный пост). Это подразумевает определенные работы, в том числе и остановку серверов, и что же UpTimeRobot? Он никак не отреагировал (либо отреагировал слишком поздно) на остановку половины серверов. И это касается не только уведомлений, в личном кабинете, спустя время UpTimeRobot также показывал 100% аптайм.

Такой казус заставил меня опять вернуться к поискам альтернативы, но все решения на рынке ужасно дорогие – под мои задачи, в среднем, 3 – 4 тыс. руб. И я подумал: «а что если поискать self-hosted альтернативы?». Сервер под такие задачи обойдется в 100-150 руб., а шанс, что одновременно упадет какой-то сайт вместе с сервисом мониторинга кране близок к нулю и этим вполне можно пренебречь.

В новых поисках я наткнулся на сервис «Upptime» и он оказался еще лучше, чем я желал – уведомления в любые мессенджеры, интерфейс приятней, чем у любой платной альтернативы и даже отдельный сервер под него не нужен – он работает на базе GitHub Pages, а это значит, что решение будет полностью бесплатным, а аптайм такого сервиса мониторинга еще выше, чем при любом self-hosted решении. Установка происходит в пару кликов: регистрируемся на GitHub, клонируем репозиторий и… ловим бан!

Я так и не понял, что произошло и что я успел нарушить за 30 секунд владения аккаунтом. Техподдержка не отвечает уже третий день. И это вынудило меня продолжить поиски.

Другие self-hosted решения на которые я натыкался оказались куском говна, ужасный интерфейс, добавление сайтов - через консоль, отсутствие уведомлений в мессенджеры или хотя бы веб-хуков. А ведь это и есть основной функционал сервиса мониторинга! Какой толк от уведомления на почту, если на нее и без того валится куча мусора, среди которого ты навряд ли заметишь нужное письмо с тревогой вовремя? Реагировать на проблемы с доступностью сайта необходимо молниеносно и лучший способ это обеспечить - уведомления в телегу.

В поисках подходящего решения я словил себя на мысли, что основной функционал подобных сервисов - это именно уведомления, а не куча настроек или графики аптайма (в личный кабинет UpTimeRobot за 2 года я заходил лишь пару раз).

А ведь уведомления - это не что-то шибко сложное, так почему бы самому не реализовать этот функционал? Сегодня мы опять будем решать свои проблемы "по бичу".

1) Создаем json-файл monitors.json, где мы будем хранить список сайтов для мониторинга

[
"https://yandex.ru",
"https://google.com"
]


2) Создаем php-файл check.php, который будет осуществлять замеры

<?php
               //API-токен нашего Telegram-бота
               $tg_token = "4555464:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
               
               //кому шлем уведомления в Telegram
               $tg_chat_id = 12345;
               
               //загружаем список сайтов для мониторинга
    $monitors = json_decode(file_get_contents('monitors.json'));
               
               //создаем массив для работы
   $output = array();
   
           //загружаем предыдущий результат
   $last_update = json_decode(file_get_contents('output.json'));
   
   
    foreach ($monitors as $monitor) {
       $status = "ok";
       $http_code = "0";

       $startScriptTime = microtime(TRUE);
       file_get_contents($monitor, false, stream_context_create(['http' => ['ignore_errors' => true]]));
       $endScriptTime = microtime(TRUE);
       $totalScriptTime = $endScriptTime - $startScriptTime;

       if ($http_response_header == NULL){
        //сначала проверим ответ и отсечем несуществующие домены
        $status = "connection error";
       } elseif ($totalScriptTime > 30){
        //укажем на слишком долгую загрузку страницы (более 30 секунд)
        $status = "conection timeout";
       } else {
        //получим http-код ответа
        $status_line = $http_response_header[0];
        preg_match('{HTTP\/\S*\s(\d{3})}', $status_line, $match);
        $http_code = $match[1];
           
        //нас устраивает ответ только 2хх, остальные - ошибка
        if ($http_code[0] != 2){
        $status = "http error";
        }
       }

       //сверим полученный статус доступности сайта с предыдущим
       //если статус изменился с момента предыдущей проверки - шлем уведомление в Telegram
       if ($last_update -> $monitor -> {'status'} != $status){
        $tg_message = "$monitor: $status (previous value: ".$last_update -> $monitor -> status.")";
        $tg_data = [
               'parse_mode' => 'Markdown',
               'chat_id' => $tg_chat_id,
               'text' => $tg_message
        ];
        $tg_response = file_get_contents("https://api.telegram.org/bot$tg_token/sendMessage?".http_build_query($tg_data));
       }
       
       $output_item['status'] = $status;
       $output_item['http_code'] = $http_code;
       $output_item['time'] = number_format($totalScriptTime * 1000, 0); //для удобства, преобразуем скорость загрузки в миллисекунды
       $output[$monitor] = $output_item;
}
//сохраняем значения
file_put_contents('output.json', json_encode($output));


3) Теперь добавим наш скрипт в планировщик задач сервера, чтобы он выполнялся каждую минуту

В принципе готово - теперь мы будем получать уведомления в Telegram когда наши сайты падают и поднимаются.

Стоит отметить, что такой подход уже лучше, чем большинство представленных на рынке сервисов мониторинга, так как даёт более реальную скорость загрузки сайтов. Большинство существующих сервисов мониторинга - зарубежные, а это значит, что скорость загрузки отечественных сайтов (которую они рисуют в своих графиках) будет нерелевантной (2 000 мс против 30-50 мс в реальности на территории РФ).

Но мы пойдем еще дальше и обеспечим 100% качество статистики. Ранее я уже писал об основной проблеме self-hosted решений, которой я решил пренебречь - сервер мониторинга может упасть вместе с каким-нибудь из проверяемых сайтов - в этом случае мы не получим уведомление об инциденте. Да, шанс возникновения такой ситуации близок к нулю, но мы поправим и это.

4) Создаем файл status.txt со значением ok и переходим на другой сервер (хостинг) для настройки резервного скрипта


5) На втором сервере создаем файл reserve_check.php

<?php
if (file_get_contents('https://example.com/status.txt' == "ok"){
//таким нехитрым способом мы проверяем доступность нашего основного сервера для мониторинга
//если с ним всё хорошо - просто копируем от туда актуалный список сайтов для првоверки и статусы по ним
file_put_contents('monitors.json', file_get_contents('https://example.com/monitors.json'));
file_put_contents('output.json', file_get_contents('https://example.com/output.json'));
} else {
//сюда копируем весь скрипт из пункта №2
}

Ну и по аналогии, добавляем этот скрипт в планировщик задач на резервном сервере.

Таким образом, даже если наш основной сервер мониторинга упадёт, мониторинг будет осуществляться резервным сервером, а пока с основным всё хорошо - обновление списка сайтов для мониторинга будет производиться в автоматическом режиме.

В список monitors.json стоит добавить и адрес основного сервера мониторинга, в этом случае мы также получим уведомление, если он упадет.

Подобный скрипт не требует установки специального ПО, поэтому может размещаться не только на виртуальных/выделенных серверах, но и на обычном шаред-хостинге. Также, такой скрипт не создает практически никакой нагрузки, поэтому для него даже не нужен какой-то отдельный сервер - его можно разместить на каком-нибудь уже существующем сервере/хостинге, просто рядом с другими сайтами и получить свой бесплатный сервис мониторинга. При этом, информация о скорости загрузки и доступности будет куда более точной, чем при использовании платных зарубежных решений.

Ах да, и про скорость загрузки - если вдруг появится необходимость посмотреть на скорость загрузки твоих сайтов, чтобы не ждать выполнение скрипта - статистику лучше получать из файла output.json, для этого создадим файл view.php и разместим в нём следующее:

<?php
$monitors = json_decode(file_get_contents('output.json'));
foreach ($monitors as $monitor) {
echo "<b>".$monitor -> time."</b>: ".$monitor -> name."<br>";
}

Нет ничего более бескомпромиссного, чем решения, созданные своими руками. Особенно, когда ты четко знаешь как это работает и что не придется ждать сюрпризов от такого сервиса. А особенно приятно, что я сэкономил до 3 500 руб. в месяц - могу позволить себе Макалан <3

Report Page