Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 16 из 25 ~16 мин +50 XP

Asynqmon: веб-интерфейс очередей

Пятнадцатый урок дал доступ к очереди из кода, но в команде есть роли, которым нужен взгляд без терминала: дежурный в три ночи, тестировщик, желающий увидеть свою задачу, продукт, оценивающий длину бэклога писем. Для них у экосистемы есть отдельный проект — asynqmon: веб-инструмент мониторинга и администрирования очередей и задач из репозитория hibiken/asynqmon, живущий независимо от библиотеки. Это не модуль вашей программы, а самостоятельное приложение: оно подключается к тому же Redis, на котором живёт asynq, и переводит внутренние структуры в страницы браузера. В уроке — запуск в Docker, разбор вкладок семи состояний, метрики успешности и ошибок и сценарий, когда asynq дашборд находит затык за минуты. К концу вы будете знать, что смотреть первым при тикете «медленно», и каких ловушек ждать от вкладок: их две, и обе стоят одного взгляда заранее.

Содержание урока · 10 разделов

До сих пор очередь отвечала вам кодом: срез GetQueueInfo, списки ListRetryTasks, ручные операции Inspector. Это форма для скриптов и алертов, но прод-инструменты смотрят не только инженеры: дежурному нужны ответы в три ночи, тестировщик хочет увидеть свою задачу глазами, продукт оценивает длину бэклога. Для них существует asynqmon — веб-инструмент мониторинга и администрирования очередей asynq: не только графики, но и кнопки действий над задачами. Это отдельный проект: он подключается к тому же Redis, на котором живёт библиотека, и переводит внутренние структуры в страницы браузера. Числа на экране совпадают с Inspector из пятнадцатого урока один в один: читаются одни и те же ключи Redis, поэтому расхождений между скриптом и asynqmon ui не бывает — бывает разное время среза. В Go-программу добавлять нечего: дашборд читает Redis напрямую и запускается отдельно от воркеров. В этом уроке поднимем его в Docker, пройдём вкладки семи состояний от active до aggregating, найдём графики обработок и ошибок и соберём сценарий отладки лагов: от тикета «письма стоят» до конкретной застрявшей задачи и её ручного запуска кнопкой.

Asynqmon ui: запуск в Docker#

Asynqmon распространяется готовым docker-образом hibiken/asynqmon, и запуск занимает одну команду: docker run --rm -p 8080:8080 hibiken/asynqmon — по адресу localhost:8080 открывается интерфейс без единой строчки в вашем Go-коде. По умолчанию контейнер ищет Redis на localhost:6379; если база живёт в соседнем контейнере или на другой машине, адрес передаётся переменной окружения REDIS_URL в формате redis://host:6379, номер базы — переменной REDIS_DB. Список флагов и переменных время от времени уточняется, поэтому сверяйте его с README репозитория asynqmon: проект живёт независимо от библиотеки и развивается своим ритмом, версии образа и версии go-пакета могут расходиться — обмен идёт через ключи Redis, а не через общий релиз. Второй типовой способ — docker-compose, где дашборд ставят рядом с Redis и воркерами: сервис asynqmon получает имя соседа в REDIS_URL и слушает порт 8080. Главное правило подключения: asynqmon должен смотреть в тот же Redis, что и ваши воркеры. Если он подключится к пустой базе dev-окружения, перед вами будет спокойный пустой интерфейс, за которым ничего не происходит, — и это не мониторинг, а обман зрения. Как только адрес совпал, интерфейс показывает все очереди, которые видит в Redis, со счётчиками по состояниям и графиками — к ним перейдём после вкладок.

Запуск образа asynqmon

GO
docker run --rm -p 8080:8080 hibiken/asynqmon

# Redis на другой машине или в другом контейнере:
docker run --rm -p 8080:8080 \
  -e REDIS_URL=redis://db.internal:6379 \
  hibiken/asynqmon

Одна команда без переменных годится для локального Redis: порт 8080 контейнера проброшен на тот же порт хоста, интерфейс откроется в браузере. REDIS_URL указывает asynqmon на тот же Redis, где живёт asynq; флаг --rm убирает контейнер после остановки. Флаги и переменные образа обновляются вместе с проектом — сверяйте их с README asynqmon.

Вкладки asynq дашборда: семь состояний#

Язык asynq дашборда — семь состояний задачи, и каждое живёт на своей вкладке; вы уже знаете их по ретраям и отложкам, теперь они станут вкладками. Pending — задача поставлена и ждёт свободного воркера. Active — хендлер исполняется прямо сейчас: строка живёт ровно столько, сколько работает обработка, постоянных жителей у вкладки нет, поэтому пустой active — норма между тиками. Scheduled — отложенные постановки ProcessIn и периодические тики. Retry — падавшие задачи с временем следующей попытки. Archived — конечная станция исчерпанных попыток и фатальных ошибок. Completed — успешные задачи, оставшиеся после работы, и здесь самое частое недоумение новичка: вкладка пустая, хотя система исправно шлёт письма. Так и задумано: без опции Retention успешная задача удаляется сразу после успеха; записываться в completed она станет только там, где постановка попросила Retention(d), и пролежит на вкладке до истечения срока. Aggregating — задачи, ждущие сборки в группах: вкладка отвечает на вопрос «копится ли пачка» одним взглядом. Ценность вкладок — арифметика симптомов: растущий retry при плоском active указывает на внешние сбои, копящийся aggregating — на остановившуюся сборку пачек, длинный scheduled при пустом pending — на обещания, которые вы дали сами опциями постановки. Таблица ниже — шпаргалка по этим семи вкладкам: где задача появляется и на что смотреть первой.

Вкладки дашборда: как задача попадает и что смотреть#

ВкладкаКак задача туда попадаетНа что смотреть
pendingПоставлена и ждёт свободного воркераРост списка без движения active — не хватает параллелизма
activeХендлер исполняется сейчасСтрока, живущая часами, — кандидат на таймаут
scheduledProcessIn, Deadline или периодикаДлина — ваши обещания на будущее
retryПопытка провалилась, пауза растётОдинаковый LastErr — внешний сервис
archivedПопытки кончились или SkipRetryДосье для ручного разбора и запуска
completedУспех с опцией Retention(d)Пусто без Retention — это норма
aggregatingЖдёт сборки в группеКопится — пачки перестали собираться

Проверка: пустая вкладка completed

Система сутки обрабатывает задачи успешно, но вкладка completed в asynqmon пуста. Почему?

Метрики успешности и ошибок#

Состояния отвечают на вопрос «где задача», а графики — «как идёт работа». Asynqmon рисует по каждой очереди динамику обработок: сколько попыток исполнилось за день и сколько из них провалилось — те же числа, что возвращает DailyStats из пятнадцатого урока, только без скрипта под рукой. Первый график полезен пропускной способностью: провал processed после деплоя виден раньше тикетов, а сравнение с предыдущими сутками показывает, насколько именно просела очередь. Второй — по ошибкам: всплеск failed при ровном processed означает, что началось что-то новое, и причина ищется на вкладке retry по LastErr; доля ошибок — число, которое бизнес понимает без перевода. Помните честность счётчиков из пятнадцатого урока: processed включает и успешные, и упавшие попытки, поэтому долю ошибок считайте сами — failed делить на processed. Для стойких алертов графиков дашборда мало: их место — в системе мониторинга, куда числа уводит двадцать третий урок; asynqmon остаётся взглядом при разборе, а не источником SLA. И маленькая деталь: статистика считается по суткам, так что сравнение «вчерашний день против сегодняшнего» — штатный режим чтения этих графиков, а не экзотика. Если график расходится с ощущениями команды, верьте графику и разбирайте, откуда ощущение: чаще всего ждут, что очередь «догонит», а она честно исполняет ровно то, что поставлено.

Дашборд рядом с Redis в compose

GO
services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
  asynqmon:
    image: hibiken/asynqmon
    ports:
      - "8080:8080"
    environment:
      - REDIS_URL=redis://redis:6379

Сервисы compose живут в одной сети, и дашборд добирается до Redis по имени сервиса: в REDIS_URL хост — redis, потому что внутри контейнера localhost — это сам asynqmon. Оба порта проброшены на хост: воркеры подключаются к localhost:6379, браузер открывает localhost:8080. Итог — все трое смотрят в одну базу.

Отладка лагов очереди#

Сценарий, ради которого asynq дашборд держат под рукой. Тикет: письма уходят с опозданием в час. Шаг первый — вкладка очереди: сравните processed с обычным днём; скорость просела — проблема производительности, а не маршрута. Шаг второй — pending: длинный список при живых active означает, что воркер не успевает, — вопрос к Concurrency или к тяжести задач. Шаг третий — retry: рост вкладки с одинаковым LastErr указывает на внешний сервис, разброс ошибок — на собственный код, а экспонента пауз уже знакома вам по шестому уроку; по LastFailedAt видно, когда всё началось. Шаг четвёртый — active: задача, висящая часами, — кандидат на таймаут из одиннадцатого урока. Шаг пятый — кнопки: Run перезапускает застрявшую после починки, Archive снимает неактуальную постановку. Каждая кнопка — та же операция, что RunTask и ArchiveTask из пятнадцатого урока: asynqmon пишет в те же ключи Redis, и задача честно переезжает между вкладками. Отличие одно — аудит: вызов из скрипта логирует ваш код, а кто нажал кнопку, история не скажет, поэтому ручные операции в проде идут через админку с логами, а дашборд остаётся инструментом первого взгляда и быстрых исправлений. Сам сценарий занимает минуты: от тикета до кнопки — пять вкладок, и каждая отсекает половину версий.

Где задача после успеха?

Прочитайте код и выберите, что он выведет:

// постановка:
client.Enqueue(task) // без asynq.Retention

// хендлер отработал, вернул nil, ретраев не было
// открываем asynqmon и ищем задачу

Безопасность дашборда в проде#

Asynqmon — административный интерфейс: права у него те же, что у Inspector из кода. На машине разработчика он не требует ничего — и это нормально: локальный Redis ничего не решает. В проде к нему относятся как к панели управления базой: доступ по VPN или за аутентификацией reverse-proxy, отдельный порт, который не торчит наружу, и правило «не публиковать дашборд без защиты». Кнопки Run, Archive и Delete меняют данные очереди так же, как одноимённые методы Inspector, поэтому авторизация и логирование действий — не опция, а часть установки: кнопка без истории — это изменение данных без автора. Если по состоянию очереди строятся отчёты для людей без прав на вмешательство, честнее read-only путь: скрипт на Inspector с одними методами чтения или экспорт метрик в систему мониторинга — там графики и живут постоянно. Бывает и обратная ситуация: браузера нет, а очередь посмотреть надо — например, по SSH на сервере в полночь. Для этого у CLI-утилиты asynq есть команда asynq dash — терминальный дашборд, который читает те же ключи Redis. Данные, форма доступа, ответственность — три разные вещи, и asynqmon закрывает только первую из них.

Правила эксплуатации asynqmon#

  • Дашборд смотрит в тот же Redis, что и воркеры: иной адрес — пустой интерфейс.
  • Пустая вкладка completed — норма: успешные задачи живут там только с Retention.
  • Кнопки Run, Archive, Delete — те же операции Inspector: логируйте, кто и что сделал.
  • В проде asynqmon прячут за аутентификацией или VPN: это админ-панель очереди.
  • Числа дашборда равны числам Inspector: расхождение — разное время среза, не баг.
  • Флаги и переменные образа сверяйте с README asynqmon — проект живёт отдельно.

Проверка: откуда цифры дашборда

Почему счётчики очереди в asynqmon совпадают с GetQueueInfo из Inspector?

Соберите команду запуска

Допишите порт хоста и имя образа asynqmon.

docker run --rm -p :8080 \ -e REDIS_URL=redis://redis:6379 \

Соберите compose для дашборда

Расставьте строки docker-compose: Redis, asynqmon, порт и адрес базы.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: asynqmon

Термин

asynqmon

нажмите, чтобы перевернуть
Определение

Отдельный репозиторий hibiken/asynqmon: веб-инструмент мониторинга и администрирования очередей asynq. Читает Redis напрямую, в код добавлять нечего.

1 / 6

Asynqmon уложен в один рабочий жест: docker run на порту 8080, семь вкладок состояний, графики обработок и кнопки тех же операций, что Inspector из кода. Мини-эксперимент: поднимите Redis и дашборд рядом, поставьте задачу с ProcessIn(2time.Minute) и посмотрите, как она переезжает scheduled → pending → active и исчезает после успеха; затем добавьте Retention(10time.Minute) и найдите её на вкладке completed. Формат прежний: код запускается локально с Go и Redis в Docker, песочница сайта показывает тематическую программу на чистом Go. Дашборд не требует кода, но и не пишет его за вас: привычка сверять вкладки после каждого деплоя отлавливает половину проблем раньше тикетов. Дальше по курсу: семнадцатый урок вернётся к хендлерам — как передавать им контекст и зависимости, а числа дашборда позже вплетутся в логи и метрики двадцать третьего урока про наблюдаемость.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

Коротко: что запомнить

  • Asynqmon — отдельный репозиторий hibiken/asynqmon: веб-инструмент мониторинга и администрирования очередей asynq.
  • Типовой запуск — docker run -p 8080:8080 hibiken/asynqmon; адрес Redis передаётся в REDIS_URL.
  • Семь состояний — семь вкладок: active, pending, scheduled, retry, archived, completed, aggregating.
  • Без Retention успешные задачи удаляются сразу: пустая вкладка completed — норма, а не симптом.
  • Числа дашборда совпадают с Inspector: читаются одни и те же ключи Redis.
  • Processed включает упавшие попытки: долю ошибок считайте сами — failed делить на processed.
  • Кнопки Run, Archive, Delete — те же операции, что RunTask и ArchiveTask из пятнадцатого урока.
  • В проде дашборд прячут за аутентификацией: это админ-панель очереди, а не витрина.

Домашнее задание

Поднимите Redis и asynqmon из compose урока и повторите путь задачи: поставьте с ProcessIn(2*time.Minute), проследите scheduled → pending → active, затем добавьте Retention(10*time.Minute) и найдите задачу на вкладке completed. Устройте затык: хендлер, который всегда падает, с MaxRetry(3) — и разберите вкладку retry по LastErr и NextProcessAt, сверяя экспоненту пауз. В финале остановите воркер на минуту и посмотрите, как ведёт себя pending при пустом active. Всё локально: Docker, Redis, браузер; песочница сайта сетевой код не исполняет.

Личные заметкиПусто
Хранятся только в вашем браузере (Asynq · Asynqmon: веб-интерфейс очередей)

Вопросы и ответы по уроку

Asynqmon нужно подключать в код воркера?

Нет: это отдельное приложение, которому нужен только адрес Redis. В Go-программу добавлять нечего, клиент и сервер работают как раньше; дашборд лишь читает те же ключи, поэтому его можно поднять и остановить в любой момент без рестартов воркеров.

Можно ли давать asynqmon дежурным в проде?

Можно, но как административный интерфейс: кнопки запуска, архивации и удаления меняют данные очереди. Минимум гигиены — аутентификация перед дашбордом в reverse-proxy или доступ по VPN, плюс логирование ручных операций. Для отчётов без права вмешательства лучше read-only путь через Inspector или экспорт метрик.

Чем asynqmon отличается от утилиты asynq?

Asynqmon — веб-интерфейс в браузере с вкладками состояний и графиками. Утилита asynq — CLI: статистика, списки задач и терминальный дашборд asynq dash для случая без браузера. Оба читают тот же Redis, что и Inspector, поэтому числа совпадают во всех трёх формах.

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

Kafka25 уроков~12 чпрактика25 уроков уже доступны

Kafka в Go: продюсеры и консьюмеры на kafka-go

Курс Kafka для Go: топики и партиции, producer и consumer, группы, оффсеты, гарантии доставки, rebalance, Admin API и мониторинг. 25 уроков.

  • Понимать топики, партиции, оффсеты и группы консьюмеров
  • Писать продюсеры с ключами, батчами и ретраями
  • Читать сообщения группой с коммитами оффсетов
  • Выбирать гарантии: at-most-once, at-least-once