- Home »

Как мониторить производительность MongoDB
Представь себе ситуацию: в пятницу вечером пришёл звонок от раздражённого клиента — его приложение медленно работает, а в выходные ожидается всплеск активности. Открываешь MongoDB, а там… всё выглядит “нормально”. Знакомо? Проблема в том, что без правильного мониторинга производительности баз данных мы летим вслепую. Эта статья поможет тебе настроить полноценную систему мониторинга MongoDB, которая будет сигнализировать о проблемах ещё до того, как они станут критичными. Разберём встроенные инструменты, внешние решения и создадим собственные скрипты для автоматизации.
Как работает мониторинг MongoDB
MongoDB генерирует огромное количество метрик в реальном времени. Основные группы данных включают:
- Операционные метрики — количество операций чтения/записи, время выполнения запросов
- Ресурсы — использование CPU, RAM, дискового пространства
- Сетевая активность — объём передаваемых данных, количество соединений
- Репликация — задержка репликации, статус членов replica set
- Блокировки — время ожидания блокировок, deadlock’и
Система мониторинга работает по принципу pull/push: либо мы периодически опрашиваем MongoDB на предмет статистики, либо настраиваем автоматическую отправку метрик во внешние системы.
Встроенные инструменты мониторинга
Начнём с того, что уже есть из коробки. MongoDB предоставляет несколько способов получения статистики:
mongostat — основной инструмент
Если тебе нужна быстрая диагностика прямо сейчас, mongostat — твой лучший друг:
mongostat --host localhost:27017 --username admin --password yourpassword
Для более детального мониторинга с интервалом в 5 секунд:
mongostat --host localhost:27017 -u admin -p yourpassword --rowcount 0 5
mongotop — анализ времени выполнения
Показывает, сколько времени MongoDB тратит на чтение и запись в каждой коллекции:
mongotop --host localhost:27017 -u admin -p yourpassword 10
Встроенные команды MongoDB
В mongo shell доступны мощные команды для диагностики:
// Общая статистика сервера
db.serverStatus()
// Статистика по конкретной базе
db.stats()
// Текущие операции
db.currentOp()
// Профилирование запросов
db.setProfilingLevel(2)
db.system.profile.find().limit(5).sort({$natural:-1}).pretty()
// Статистика репликации
db.getReplicationInfo()
Настройка внешних систем мониторинга
Prometheus + Grafana
Самая популярная связка для мониторинга. Устанавливаем MongoDB Exporter:
# Скачиваем и устанавливаем
wget https://github.com/percona/mongodb_exporter/releases/download/v0.40.0/mongodb_exporter-0.40.0.linux-amd64.tar.gz
tar -xzf mongodb_exporter-0.40.0.linux-amd64.tar.gz
sudo mv mongodb_exporter /usr/local/bin/
# Создаём systemd сервис
sudo tee /etc/systemd/system/mongodb_exporter.service > /dev/null <
Конфигурация Prometheus (prometheus.yml):
scrape_configs:
- job_name: 'mongodb'
static_configs:
- targets: ['localhost:9216']
scrape_interval: 30s
metrics_path: /metrics
Zabbix мониторинг
Для любителей Zabbix создаём простой скрипт мониторинга:
#!/bin/bash
# /usr/local/bin/mongodb_check.sh
MONGO_HOST="localhost"
MONGO_PORT="27017"
MONGO_USER="monitoring"
MONGO_PASS="password"
case $1 in
connections)
mongo --host $MONGO_HOST:$MONGO_PORT -u $MONGO_USER -p $MONGO_PASS --quiet --eval "db.serverStatus().connections.current"
;;
operations_per_sec)
mongo --host $MONGO_HOST:$MONGO_PORT -u $MONGO_USER -p $MONGO_PASS --quiet --eval "db.serverStatus().opcounters.query"
;;
memory_usage)
mongo --host $MONGO_HOST:$MONGO_PORT -u $MONGO_USER -p $MONGO_PASS --quiet --eval "db.serverStatus().mem.resident"
;;
replication_lag)
mongo --host $MONGO_HOST:$MONGO_PORT -u $MONGO_USER -p $MONGO_PASS --quiet --eval "printjson(db.getReplicationInfo())"
;;
esac
Создание собственной системы мониторинга
Иногда нужно что-то специфическое. Вот Python-скрипт для создания собственной системы мониторинга:
#!/usr/bin/env python3
import pymongo
import json
import time
import logging
from datetime import datetime
class MongoMonitor:
def __init__(self, connection_string, database_name="admin"):
self.client = pymongo.MongoClient(connection_string)
self.db = self.client[database_name]
def get_server_stats(self):
"""Получаем основные метрики сервера"""
stats = self.db.command("serverStatus")
return {
'timestamp': datetime.now().isoformat(),
'connections': stats['connections'],
'operations': stats['opcounters'],
'memory': stats['mem'],
'network': stats['network'],
'locks': stats.get('locks', {}),
'globalLock': stats['globalLock']
}
def get_slow_queries(self, threshold_ms=100):
"""Находим медленные запросы"""
# Включаем профилирование
self.db.set_profiling_level(2, slow_ms=threshold_ms)
# Получаем последние медленные запросы
slow_queries = list(self.db.system.profile.find().sort([('$natural', -1)]).limit(10))
return slow_queries
def check_replication_health(self):
"""Проверяем здоровье репликации"""
try:
repl_status = self.db.command("replSetGetStatus")
return {
'set': repl_status['set'],
'members': [
{
'name': member['name'],
'health': member['health'],
'state': member['stateStr'],
'lag': member.get('optimeDate', 'N/A')
}
for member in repl_status['members']
]
}
except Exception as e:
return {'error': str(e)}
def monitor_loop(self, interval=60):
"""Основной цикл мониторинга"""
while True:
try:
stats = self.get_server_stats()
slow_queries = self.get_slow_queries()
repl_health = self.check_replication_health()
# Здесь можно добавить логику алертов
self.check_alerts(stats)
# Выводим или сохраняем статистику
print(json.dumps(stats, indent=2))
time.sleep(interval)
except Exception as e:
logging.error(f"Monitoring error: {e}")
time.sleep(interval)
def check_alerts(self, stats):
"""Проверяем пороговые значения"""
# Проверяем количество соединений
if stats['connections']['current'] > 1000:
self.send_alert(f"High connections: {stats['connections']['current']}")
# Проверяем использование памяти
if stats['memory']['resident'] > 4000: # 4GB
self.send_alert(f"High memory usage: {stats['memory']['resident']}MB")
# Проверяем время блокировок
if stats['globalLock']['totalTime'] > 1000000: # микросекунды
self.send_alert(f"High lock time: {stats['globalLock']['totalTime']}")
def send_alert(self, message):
"""Отправляем алерт"""
# Здесь можно добавить отправку в Slack, email, webhook
print(f"ALERT: {message}")
# Использование
if __name__ == "__main__":
monitor = MongoMonitor("mongodb://monitoring_user:password@localhost:27017/admin")
monitor.monitor_loop(30) # Проверка каждые 30 секунд
Практические кейсы и решения
Кейс 1: Медленные запросы
Симптомы: высокая нагрузка на CPU, медленные ответы приложения.
Диагностика:
# Включаем профилирование медленных запросов (>100ms)
db.setProfilingLevel(2, {slowms: 100})
# Ищем самые медленные запросы
db.system.profile.find({millis: {$gt: 100}}).sort({millis: -1}).limit(5).pretty()
# Анализируем план выполнения
db.collection.find({field: "value"}).explain("executionStats")
Кейс 2: Проблемы с репликацией
Симптомы: высокая задержка репликации, частые failover.
Диагностика:
# Проверяем статус replica set
rs.status()
# Проверяем конфигурацию
rs.conf()
# Мониторим задержку репликации
rs.printReplicationInfo()
rs.printSlaveReplicationInfo()
Таблица сравнения инструментов мониторинга
Инструмент | Сложность настройки | Возможности | Стоимость | Лучше всего для |
---|---|---|---|---|
mongostat/mongotop | Низкая | Базовые метрики | Бесплатно | Быстрой диагностики |
MongoDB Compass | Низкая | GUI, визуализация | Бесплатно | Разработчиков |
Prometheus + Grafana | Средняя | Полный мониторинг | Бесплатно | Production окружений |
MongoDB Atlas | Низкая | Управляемый сервис | Платно | Облачных решений |
Zabbix | Высокая | Enterprise мониторинг | Бесплатно | Корпоративных сред |
Автоматизация и скрипты
Bash-скрипт для автоматических алертов
#!/bin/bash
# /usr/local/bin/mongodb_alerts.sh
MONGO_HOST="localhost:27017"
MONGO_USER="monitoring"
MONGO_PASS="password"
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
# Проверяем количество соединений
CONNECTIONS=$(mongo --host $MONGO_HOST -u $MONGO_USER -p $MONGO_PASS --quiet --eval "db.serverStatus().connections.current")
if [ $CONNECTIONS -gt 1000 ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"⚠️ MongoDB Alert: High connections ($CONNECTIONS)\"}" \
$WEBHOOK_URL
fi
# Проверяем использование памяти
MEMORY=$(mongo --host $MONGO_HOST -u $MONGO_USER -p $MONGO_PASS --quiet --eval "db.serverStatus().mem.resident")
if [ $MEMORY -gt 4000 ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"⚠️ MongoDB Alert: High memory usage (${MEMORY}MB)\"}" \
$WEBHOOK_URL
fi
# Проверяем статус репликации
REPL_LAG=$(mongo --host $MONGO_HOST -u $MONGO_USER -p $MONGO_PASS --quiet --eval "
var status = rs.status();
var lag = 0;
if (status.ok) {
var primary = status.members.find(m => m.state === 1);
var secondary = status.members.find(m => m.state === 2);
if (primary && secondary) {
lag = (primary.optimeDate - secondary.optimeDate) / 1000;
}
}
print(lag);
")
if [ $(echo "$REPL_LAG > 10" | bc) -eq 1 ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"⚠️ MongoDB Alert: High replication lag (${REPL_LAG}s)\"}" \
$WEBHOOK_URL
fi
Добавляем в cron для автоматического выполнения:
# Каждые 5 минут
*/5 * * * * /usr/local/bin/mongodb_alerts.sh
Оптимизация производительности на основе мониторинга
Настройка индексов
Используем данные профилирования для создания эффективных индексов:
# Находим запросы без индексов
db.system.profile.find({
"command.filter": {$exists: true},
"planSummary": "COLLSCAN"
}).pretty()
# Создаём составные индексы на основе анализа
db.collection.createIndex({field1: 1, field2: -1})
# Проверяем использование индексов
db.collection.getIndexes()
db.stats().indexSizes
Настройка connection pool
# В конфигурации приложения
mongodb://user:password@localhost:27017/database?maxPoolSize=100&minPoolSize=10&maxIdleTimeMS=30000
Интеграция с другими инструментами
ELK Stack интеграция
Для централизованного логирования настраиваем отправку метрик в Elasticsearch:
# Конфигурация Filebeat для MongoDB логов
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/mongodb/mongod.log
fields:
service: mongodb
environment: production
output.elasticsearch:
hosts: ["localhost:9200"]
index: "mongodb-logs-%{+yyyy.MM.dd}"
Интеграция с Ansible
Playbook для автоматической настройки мониторинга:
---
- name: Setup MongoDB monitoring
hosts: mongodb_servers
tasks:
- name: Install MongoDB exporter
get_url:
url: "https://github.com/percona/mongodb_exporter/releases/download/v0.40.0/mongodb_exporter-0.40.0.linux-amd64.tar.gz"
dest: /tmp/mongodb_exporter.tar.gz
- name: Extract exporter
unarchive:
src: /tmp/mongodb_exporter.tar.gz
dest: /usr/local/bin/
remote_src: yes
- name: Create monitoring user
mongodb_user:
database: admin
name: monitoring_user
password: "{{ monitoring_password }}"
roles: clusterMonitor,read
- name: Setup systemd service
template:
src: mongodb_exporter.service.j2
dest: /etc/systemd/system/mongodb_exporter.service
notify: restart mongodb_exporter
Интересные факты и нестандартные применения
Вот несколько интересных возможностей, которые многие упускают:
- Мониторинг на уровне операций — можно отслеживать конкретные типы операций и их влияние на производительность
- Геораспределённый мониторинг — при использовании sharding можно мониторить производительность по географическим регионам
- Предиктивная аналитика — используя machine learning на исторических данных мониторинга, можно предсказывать будущие проблемы
- Автоматическое масштабирование — на основе метрик можно автоматически добавлять новые узлы в cluster
Лично я использую комбинацию Prometheus + Grafana + custom Python скриптов для создания “умных” алертов, которые учитывают не только текущие значения метрик, но и их тренды.
Новые возможности для автоматизации
Правильно настроенный мониторинг открывает массу возможностей для автоматизации:
- Автоматическое создание индексов — на основе анализа медленных запросов
- Динамическое изменение конфигурации — адаптация параметров в зависимости от нагрузки
- Предупреждающие действия — автоматическое масштабирование при приближении к лимитам
- Интеграция с CI/CD — блокировка деплоя при аномальных показателях базы
Если планируешь разворачивать серьёзную MongoDB инфраструктуру, рекомендую взглянуть на VPS решения или выделенные серверы для обеспечения стабильной производительности.
Заключение и рекомендации
Мониторинг MongoDB — это не просто “nice to have”, а критически важная часть любой production системы. Начинай с простых встроенных инструментов, но не останавливайся на них. Полноценная система мониторинга должна включать:
- Реальное время мониторинга ключевых метрик
- Исторические данные для анализа трендов
- Автоматические алерты по критическим событиям
- Интеграцию с системами уведомлений
- Автоматизацию рутинных задач
Мой совет: начни с Prometheus + Grafana связки — это золотой стандарт для мониторинга MongoDB в production. Добавь к этому несколько custom скриптов для специфических задач, и у тебя будет система, которая не только покажет проблемы, но и поможет их предотвратить.
Помни: лучший мониторинг — тот, который работает до того, как что-то сломается. Не жди пятничного звонка от клиента — настрой систему правильно прямо сейчас!
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.