Рубрика:

Опубликовано:

12.07.2021

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

Статьи
12.07.2021

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

Кучу лет назад, я воспользовался первым попавшимся сервисом, который позволял осуществлять мониторинг бесплатно – это был 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 $name=>$monitor) {
		echo "<b>".$monitor -> time."</b>: ".$name."<br>";
	}

Поделиться
Share on vk
Share on twitter
Share on facebook
Share on telegram
Share on whatsapp

Обсудите ваш проект с менеджером

    Я согласен на обработку персональных данных согласно политике конфиденциальности

    Звоните
    Пишите

    Meta* признана экстремистской организацией на территории РФ

    Служба поддержки

      Тариф Базовый Продвинутый Профессиональный
      При оплате на 1 год 390 руб./мес. 450 руб./мес. 490 руб./мес.
      При оплате на 2 года 332 руб./мес. 383 руб./мес. 417 руб./мес.
      При оплате на 3 года 273 руб./мес. 315 руб./мес. 343 руб./мес.

      Реквизиты для рассчётного счета

      Заполните реквизиты вашей организации, а мы подготовим и направим счет вам на электронную почту. Обратите внимание, при оплате через расчетный счет срок выполнения работ увеличен до 10 рабочих дней.

        Я согласен на обработку персональных данных согласно политике конфиденциальности