«no memcache server available»: 502 на всей веб-почте Zimbra

У клиента-торговой компании на Дмитровском шоссе во вторник утром веб-почта начала отдавать 502 всем сразу. При этом mailboxd был жив, службы показывали Running, а у половины сотрудников почта на телефонах продолжала работать. Разбираю, как Zimbra маршрутизирует подключение через route lookup и memcached и почему эта связка рвётся тихо.

Когда 502 приходит на пустом месте

Есть аварии, которые выглядят страшнее, чем они есть. И есть такие, которые выглядят проще. Эта — вторая.

Картина: пользователи открывают веб-почту и получают короткую страницу с числом 502. Все, одновременно, без исключений. Админ идёт на сервер, смотрит службы — всё Running. Смотрит место — есть. Смотрит нагрузку — нормальная. Пробует почту на своём телефоне — а она работает. И вот здесь начинается самое интересное, потому что дальше человек обычно перезапускает всё подряд, что-то случайно чинит на двадцать минут, потом оно ломается снова, и к обеду сервер уже перезагружен трижды.

Если вы узнали себя — дело почти наверняка не в почте. Дело в том, что стоит перед почтой. У Zimbra между пользователем и его ящиком работают два посредника, о которых вспоминают в последнюю очередь: обработчик маршрутов на отдельном порту и маленький кэш, который хранит ответы этого обработчика. Когда рвётся связь между ними, ящики целы, письма на месте, а зайти нельзя.

Вторник, 20 февраля 2024-го: хронология

Торговая компания, склад и офис на Дмитровском шоссе, 48 рабочих мест, оптовые поставки инструмента. Заявки от клиентов приходят почтой — это важно для понимания цены вопроса. Zimbra 9 Open Source на своей виртуалке, обслуживает их подрядчик, меня позвали как второе мнение.

В ночь с понедельника на вторник у них было плановое окно: обновили ядро гостевой ОС и перезагрузили машину. Утром — 502.

Первое, что я открыл, — лог прокси, а не лог почты:

$ tail -n 5 /opt/zimbra/log/nginx.log
2024/02/20 09:04:11 [error] 3184#0: *217 no memcache server available,
 cannot post request, client: 10.20.4.61, server: mail.example.ru,
 request: "POST /service/soap/AuthRequest HTTP/1.1"
2024/02/20 09:04:12 [error] 3184#0: *219 no memcache server available,
 cannot post request, client: 10.20.4.88, server: mail.example.ru

Строка исчерпывающая. Прокси не может достучаться до кэша и поэтому отказывается обрабатывать запрос. Клиенту это приезжает как 502.

Почему при этом работали телефоны: у тех, кто уже был подключён по IMAP, сессии держались, маршрут для них был получен раньше и лежал в кэше. Новый вход падал у всех. К десяти утра, когда часть телефонов перезашла, перестало работать и там.

Ложная версия: «просто mailboxd не поднялся»

Первая версия была не моя, но я её честно проверил, потому что она правильная в большинстве случаев. По статистике самая частая причина ошибок проксирования — это упавший mailboxd на целевом сервере: обработчик маршрутов не отвечает, прокси нечего сказать клиенту, тот получает отказ.

Версия ломается о два факта. Первый: службы были подняты. Второй, важнее, — обработчик маршрутов отвечал:

$ curl -k -s -o /dev/null -w "%{http_code}\n" https://$(zmhostname):7072/service/extension/nginx-lookup
401

Код 401 здесь не ошибка, а хороший знак: сервлет живой и требует данных авторизации, которых я ему не дал. Если бы mailboxd лежал, я бы получил отказ в соединении или пустоту.

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

И вот здесь я сделал то, за что до сих пор себя ругаю. Нашёл на форуме обходной приём, применил его, не разобравшись:

zmprov mcf zimbraMailProxyMaxFails 0
zmproxyctl restart

Почта поднялась в 10:40 и проработала ровно сорок минут. В 11:20 502 вернулся. Я замаскировал симптом и потерял почти час, потому что перестал искать причину, решив, что уже нашёл. Приём рабочий — но он про допустимое число неудачных попыток, а не про адрес, по которому эти попытки идут.

Как Zimbra на самом деле пускает вас в ящик

Разложу цепочку по шагам, потому что без неё дальше ничего не читается.

  • Пользователь приходит на публичный порт — 443 для веба, 993 или 995 для почтовых клиентов. Его встречает не почта, а прокси на nginx.
  • Прокси не знает, где лежит ящик этого человека. Он делает внутренний HTTP-запрос к обработчику маршрутов — сервлету на почтовом сервере, порт 7072.
  • Обработчик смотрит в каталог и отвечает: ящик такой-то обслуживается таким-то сервером.
  • Ответ кладётся в memcached на порт 11211, время жизни записи по умолчанию — один час. Пока запись жива, прокси не дёргает обработчик повторно.

Смысл кэша прост: на тысяче подключений в минуту дёргать сервлет каждый раз дорого. Смысл аварии тоже прост: если кэш недоступен, прокси считает, что не может выполнить свою работу, и не пытается ходить к обработчику напрямую. Он отказывает.

Конфигурация прокси не пишется руками — она генерируется. Утилита zmproxyconfgen собирает /opt/zimbra/conf/nginx.conf из шаблонов и значений в каталоге при каждом старте прокси. Отсюда следует неприятное: правку, внесённую в атрибут месяц назад, вы увидите в работе не месяц назад, а при ближайшем перезапуске. Ровно это у нас и произошло.

Проверьте у себя за две минуты

Три строки. Первая — что видит прокси в логе, вторая — куда он собирается ходить, третья — что реально слушает порт кэша.

su - zimbra
grep -c "no memcache server available" /opt/zimbra/log/nginx.log
grep -A3 "memcache" /opt/zimbra/conf/nginx.conf | grep servers
ss -lntp | grep 11211
zmprov gs $(zmhostname) zimbraMemcachedBindAddress

Сопоставляем вторую строку с третьей, а четвёртую держим рядом как «эталон»: именно её значение генератор конфига подставит в nginx.conf при следующем перезапуске.

Что увиделиЧто это значитКогда действовать
В логе ноль совпадений, адреса во второй и третьей строке совпадаютСвязка целаяНичего не трогать
Адрес в nginx.conf — IP хоста, а слушает 127.0.0.1Мина: сработает при первом же перезапуске проксиДо ближайшего планового окна
Слушает ::1 вместо 127.0.0.1Кэш поднят только на IPv6, сервлет с ним не свяжетсяСегодня
Третья строка пустаяmemcached не запущен вовсеНемедленно
Файла /opt/zimbra/conf/nginx.conf нетГенератор конфига упал, прокси не стартовалНемедленно
502 был на прошлой неделе и «прошёл сам» примерно через часПодпись залипшего маршрута в кэше после переноса или переименования ящикаНа этой неделе

Отдельно посмотрите список обработчиков маршрутов, которые прокси вообще видит:

$ zmprov garpu
https://mail.example.ru:7072/service/extension/nginx-lookup

Пустой вывод здесь — тоже диагноз: почтовый сервер не помечен как цель для поиска маршрута, и прокси не знает, у кого спрашивать.

Три способа порвать эту связку

Первый и самый частый — разъехавшиеся адреса. Кэш переводят слушать только на локальную петлю: это разумная мера, наружу его торчать нечему. А сгенерированный конфиг прокси продолжает ссылаться на прежний адрес хоста в локальной сети. Именно это было у нас: подрядчик закрывал замечания аудита в январе, а выстрелило 20 февраля, при первом после этого перезапуске.

$ zmprov gs $(zmhostname) zimbraMemcachedBindAddress
zimbraMemcachedBindAddress: 127.0.0.1

$ grep servers /opt/zimbra/conf/nginx.conf
    servers   10.20.0.11:11211;

Лечится приведением к одному значению и перегенерацией конфига. Аварийный вариант, если разбираться некогда, — прописать адрес в шаблоне явно, закомментировав подстановку, и перезапустить прокси. Я так делать не люблю: правка в шаблоне переживает не каждое обновление, и через год кто-то будет искать её так же, как я искал причину.

Второй — кэш только на IPv6. Когда memcached поднят на ::1, сервлет не может к нему привязаться и падает с сообщением про то, что ему нужен хотя бы один сервер для подключения. Симптом в браузере тот же самый, а причина в одном символе конфигурации.

Третий — конфиг прокси не сгенерировался. Генератор бросает исключение, файл nginx.conf не создаётся, nginx не стартует. Тут 502 вы даже не увидите — будет отказ в соединении. Проверять руками:

$ /opt/zimbra/libexec/zmproxyconfgen
$ ls -l /opt/zimbra/conf/nginx.conf
-rw-r----- 1 zimbra zimbra 18244 Feb 20 11:52 /opt/zimbra/conf/nginx.conf
$ zmproxyctl restart

Залипший маршрут: отдельная история

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

Механика: маршрут для этого человека уже лежит в кэше и указывает на прежний сервер. Ящика там больше нет. Час — время жизни записи — пользователь будет получать ошибки или, что хуже, видеть пустую почту, а вы будете проверять сам ящик, который в полном порядке.

Ждать час не обязательно, кэш сбрасывается рестартом:

zmmemcachedctl restart
zmproxyctl restart

Издержка — все активные сессии переустановятся. На сорока восьми пользователях это незаметно, на шестистах уже ощутимо, поэтому переносы ящиков лучше планировать так, чтобы сброс кэша попадал в то же окно.

Практическое правило, которое я вывел для себя: любая работа, меняющая расположение ящика, заканчивается рестартом кэша. Не «если пожалуются», а всегда. Стоит десять секунд, экономит полдня разбирательств через неделю, когда связь между переносом и жалобой уже никто не проведёт.

Чем закончилось и во что обошлось

Настоящую причину я нашёл в 11:40, починил к 12:10. Непрерывного простоя в три часа не было: почта лежала с 09:00 до 10:40, потом сорок минут работала на моём обходном приёме, а с 11:20 до 12:10 лежала снова. Суммарно 2 часа 30 минут двумя кусками — и это та цифра, которую я считаю честной.

Заявки от клиентов у них приходят почтой, поэтому простой считается не в абстрактных человеко-часах. Реально работать не могли 30 человек: продажи, снабжение и бухгалтерия. 30 × 2,5 часа = 75 человеко-часов; час работы сотрудника вместе с налогами и рабочим местом компания считает по 520 рублей — это 39 000 рублей оплаченного и потерянного времени. Дороже вышло другое: из 34 писем с заявками одно было запросом на срочную отгрузку от постоянного клиента, он не дождался ответа и в тот же день купил у конкурента. Отгрузка на 173 000 рублей просто не состоялась.

СтатьяЦифра
Простой веб-почты2 ч 30 мин двумя кусками, рабочий вторник
Затронуто сотрудников48, из них 19 в отделе продаж
Заявок, увиденных с задержкой34 письма, три отгрузки сдвинулись на сутки
Оплаченное время сотрудников впустую75 человеко-часов × 520 ₽ = 39 000 ₽
Несостоявшаяся отгрузка173 000 ₽ — клиент не дождался и ушёл к конкуренту
Мой счёт за второе мнение3 часа × 4 300 ₽ = 12 900 ₽
Стоимость профилактики20 минут сверки адресов раз в месяц
Потеряно на ложной версии и обходном приёмеоколо 1 часа моего времени
Перезагрузок сервера за утро до моего приезда3, все бесполезные

Занятно, что сама правка заняла восемь минут: привести адрес к одному значению, перегенерировать конфиг, перезапустить прокси. Ещё двадцать я стоял и смотрел, как люди заходят, — под нагрузкой, а не «у меня открылось». Всё остальное время ушло на то, чтобы понять, куда смотреть. Это типично для этого класса аварий и это же делает их дорогими — они не требуют квалификации, они требуют знания, что такая связка вообще существует.

Что мы поменяли после: вернули значение допустимых неудач к дефолтному (мой обходной приём я снял, он там был лишним), завели проверку соответствия адресов в ежемесячный чек-лист и добавили в мониторинг простой счётчик строк с этой ошибкой в логе прокси. Порог — единица. За два года сработал один раз, в декабре 2025-го, когда обновляли гипервизор и машина поднялась с другим набором интерфейсов.

Если у вас сейчас 502 или он был на прошлой неделе и «прошёл сам» — прогоните три команды из раздела про двухминутную проверку и пришлите мне вывод. Скажу, что у вас: разъехались адреса, не поднялся кэш или это вообще не про прокси. Разбор занимает у меня минут двадцать.

Частые вопросы

У нас 502 прошёл сам через час. Это точно был memcached?

Скорее нет. Самопроизвольное восстановление ровно через час — это подпись залипшего маршрута: запись в кэше жила час, истекла, прокси заново спросил обработчик и получил правильный ответ. Такое бывает после переноса ящика или после смены адреса почтового сервера. Если же кэш недоступен физически, само оно не пройдёт — 502 будет держаться до тех пор, пока вы не поднимете кэш или не почините адрес. Различить эти два сценария помогает счётчик строк в логе прокси: при залипшем маршруте ошибок про недоступный кэш там не будет вовсе.

Можно ли просто отключить прокси и пустить всех напрямую в mailboxd?

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

Что делает zimbraMailProxyMaxFails и почему это советуют на форумах?

Это допустимое число неудачных попыток, после которого прокси помечает цель как нерабочую. Значение ноль означает, что цель не будет исключаться из обслуживания. У части людей после такой правки ошибка переставала воспроизводиться, отсюда и совет. Но это работа с последствием, а не с причиной: если кэш недоступен по адресу, прокси всё равно не сможет положить туда ответ. У меня этот приём дал сорок минут работающей почты и час потерянного времени — я решил, что нашёл причину, и перестал искать.

Как понять, что дело не в прокси, а в самой почте?

Спросить обработчик маршрутов напрямую по порту 7072. Если он отвечает кодом 401 — сервлет жив, mailboxd работает, ищите проблему между прокси и кэшем. Если соединение не устанавливается или висит — почтовая часть лежит, и вся история про кэш к вам не относится, идите смотреть журнал mailboxd и память. Это самая быстрая развилка в диагностике: одна команда, два принципиально разных пути дальше.

Стоит ли выносить memcached на отдельный хост?

Для установки на 48 или даже на 300 пользователей — нет, смысла ноль, вы только добавите себе точку отказа и сетевую задержку в каждый вход. Отдельный кэш имеет смысл в многосерверных конфигурациях, где несколько прокси должны видеть одни и те же маршруты. И если вы туда идёте, закладывайте сразу мониторинг доступности порта 11211 с каждого прокси: в такой схеме сетевые проблемы между узлами выглядят точно так же, как эта авария, и ищутся вдвое дольше.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#Zimbra#proxy#memcached#nginx#авария
Комментарии 0

Оставить комментарий

загрузка...

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.