ReOpenLDAP — сквозь тернии в «МегаФон», путь за год (Леонид Юрьев, OSSDEVCONF-2016)
Материал из 0x1.tv
Содержание
Аннотация
- Докладчик
- Леонид Юрьев
Проект был инициирован в 2014 году для решения проблем, возникших при эксплуатации исходного OpenLDAP в инфраструктуре одного из крупнейших Российских операторов мобильной связи.
За два года проект выведен «на орбиту» высоконагруженной промышленной эксплуатации. Сейчас ReOpenLDAP успешно работает во всех филиалах ПАО МегаФон по всей России и одновременно доступен как OpenSource.
В очной сессии будет краткий рассказ о том, что удалось сделать за последний год и озвучены планы. В печатных тезисах дополнительно немного предыстории и напоминаний о ранее проделанной работе.
Видео
Слайды
Расширенные тезисы
Кратко
Хочу кратко напомнить, как мы пришли к разработке собственно клона общеизвестного OpenLDAP. Затем рассказать, что было сделано в нашем проекте, с акцентом на последний год.
Если говорить о результате, то тесты и опыт эксплуатации позволяют сделать вывод, что наш ReOpenLDAP — один из немногих годных к высоконагруженной промышленной эксплуатации (возможно, единственный).
Предыстория
Примерно в 2013 году Петер-Сервис приступил к разработке одной из подсистем (NGDR) для инфраструктуры «МегаФона». Один из вариантов реализации предполагал использование высокопроизводительного LDAP-сервера.
Следует отметить, что сценарий использования, а особенно расчётные нагрузки, совершенно не соответствовали традиционным режимам работы LDAP-серверов. Например, предполагаемые 10 тысяч обновлений в секунду на 1–2 порядка превышают то, что может обеспечить большинство LDAP-серверов.
Среди вариантов, конечно, также рассматривались предназначенные для таких сценариев «чемпионские» key-value хранилища, как например tarantool.org. Однако парадигма LDAP и сам протокол очень любимы в телеком-отрасли. Соответственно использование любого не-LDAP-хранилища в скором времени потребовало бы реализации к нему доступа посредством LDAP. Поэтому всё-таки решили попробовать все доступные LDAP-серверы.
В процессе тестов быстро выяснилось, что необходимую производительность даёт только общеизвестный OpenLDAP. При этом крайне важным было то, что нагрузка по записи не приводила к деградации производительности по чтению, и в основном ограничивалась производительностью дисков. Это принципиальное отличие, как и производительность, хорошо объяснялись свойствами движка хранения LMDB.
OpenLDAP также поддерживает синхронизацию содержимого каталога, в том числе в «горячем» режиме, включая топологию multi-master. Массовость использования и 25-летняя история открытого проекта позволяли надеяться, что проблем со стабильностью не будет. По совокупности факторов мы опрометчиво решили закрыть глаза на однократное падение OpenLDAP в процессе наших предварительных тестов. Летом 2014 года разрабатываемая подсистема была включена в тестовую эксплуатацию…
Стоит отметить, что изначально Петер-Сервис не собирался «чинить» OpenLDAP своими силами и тем более делать клон проекта. При первых проблемах компания обратилась за коммерческой поддержкой в Symas Corp. Однако Symas Corp не решилась взять обязательства с фиксированием каких-либо сроков и неустойкой за их несоблюдение.
Исходные проблемы
Для понимания контекста следует сказать пару слов о целевой среде: «NGDR представляет собой UDR (User Data Repository), согласно стандарту 3GPP 23.335, и является централизованным узлом для хранения данных обо всех видах услуг абонентов в ИТ-инфраструктуре оператора связи», см. bit.ly/2d0103K
Всего шесть филиалов по России, в каждом:
- Объём данных до 100 ГБ, от 10 до 70 миллионов записей.
- Порядка 10 тысяч обновлений в секунду, до 50 тысяч читающих запросов в секунду.
- Сбой при чтении — каскад сбоев в инфраструктуре, неполученная услуга, недовольство абонента и потеря прибыли оператором.
- Сбой при записи — потеря или искажение изменений в наборе услуг и тарифных опциях.
Проблемы были разные и многогранные, большинство из них мы долгое время не замечали. Так, например, сценарий воспроизведения сбоев репликации был найден только в августе 2015, а до этого мы списывали странные расхождения в данных на последствия других проблем.
Почти всегда было неясно, где искать причину. Временами приходилось переделывать все «подозрительные места», а это примерно 80% исходного кода ;)
Устраняли проблемы «послойно», по мере понимания и естественного смещения фокуса от «горим, пожар» до «хорошо бы поправить».
- Повреждение БД и падения внутри движка LMDB.
- Последствия архитектурных изъянов LMDB. Например, выполнение «ldapsearch бла-бла-бла | less» приводило к переполнению БД, отказу по записи и последующей деградации производительности до пересоздания БД.
- Утечки памяти, отказы в обслуживании из-за OOM.
- Разнообразные падения, особенно при разрыве соединений под высокой нагрузкой.
- Распухание базы вплоть до удвоения её физического объёма.
- Проблемы в механизме репликации, от потери отдельных изменений до внезапного обнуления DIR.
- Шатающиеся тесты, редкие сбои и падения.
Следует отметить, что для абонентов и оператора в целом эти сбои не стали катастрофой благодаря «военным» регламентам внутри «МегаФона», а также чёткой работе инженеров службы эксплуатации.
Почему «форк»?
Вынуждено. В конце 2014 года мы осознали, что не сможем эффективно устранять проблемы и одновременно возвращать изменения в OpenLDAP.
- Первым «звоночком» была ситуация с ошибками в движке LMDB: разделяемый несколькими процессами memory-mapped файл, lock-free алгоритмы и ни одного «volatile» в исходных текстах. При этом убедить авторов в наличии ошибки удалось только показательным тестом с assert-проверкой, а до этого «мы не понимали дизайна».
- Затем мейнтейнеры Symas отказались принимать патчи, мотивировав отказ использованием variadic macro в одном из них. Казус будет непонятен без ряда деталей:
- Суммарно наши патчи устраняли почти 5000 предупреждений, большей частью безобидных, но в этом море годами оставались незамеченными реальные проблемы.
- Только один из патчей использовал variadic macro, тогда как остальные устраняли явные ошибки и недочёты. При этом grep по исходному коду обнаруживал variadic macro и без наших изменений.
- Мы не нашли платформ или систем, на которых можно было бы собрать OpenLDAP и при этом не было компилятора с поддержкой variadic macro, ни пользователей таких систем, ни информации о последних успешных проверках или сборках на таких платформах.
В результате, мы пришли к выводу что нам «нужно ехать, а не шашечки», и в первых числах 2015 года основали ReOpenLDAP. При этом отдельный форк движка LMDB не предполагался. Но осенью 2015 его пришлось сделать по техническим причинам (при подготовке к докладу на Highload++2015), а название «MDBX» было выбрано, как первый подходящий вариант.
Доработки
Рассказывать или даже просто перечислять все исправления «падений» и утечек памяти смысла нет. Поэтому только ключевые и существенные доработки, которые есть только в ReOpenLDAP или в MDBX:
В 2014 году починили то, что не давало спать:
- Поддержка LIFO при сборке мусора и повторном использовании страниц в MDBX. Этим мы решили проблему неэффективного использования кэша обратной записи, а также устранили лишнее вымывание кэша страниц ОС. Проще говоря, при наличии BBWC производительность по записи может быть увеличена в разы. Подробно это было рассмотрено в отдельном докладе, см. highload.ru/2015/abstracts/1831.html
- Механизм OOM-Handler в MDBX позволил смягчить (фактически нейтрализовать) проблему «зависших читателей» и устранить отказы в обслуживании из-за переполнения БД. Знатокам может показаться, что проблема решена в последних версиях OpenLDAP, так как реализован рестарт «долгих» транзакций чтения, в том числе при ожидании сети. Однако это не так — снижена лишь вероятность возникновения проблем.
В 2015 году устранили падения и замеченные системные проблемы:
- В MDBX устранена специфическая проблема возможного разрушения БД при использовании read-write отображения в память. Может показаться странным, но оригинальный движок LMDB при некоторых обстоятельствах может безвозвратно потерять всю базу — даже если приложение периодически явно выполняет синхронизацию данных с диском.
- Устранено сохранение лишних нормализованных значений LDAP-атрибутов, когда нормализованное и «обычное» значения равны. Эта незаметная и вроде бы безобидная ошибка на деле приводит к удвоению размера каждой записи и к пропорциональной деградации производительности в лучшем случае.
- Поддержка «limit-concurrent-refresh», что позволяет избежать одинаковых одновременных обновлений на стороне получателя репликации и таким образом существенно ускорить синхронизацию, одновременно с уменьшением пикового потребления памяти.
За последний год
- Во-первых, починили репликацию:
- Устранение логических ошибок в механизме репликации (синхронизации содержимого), которые приводят к потере отдельных изменений:
- Упущены несколько проверок при обработке уведомлений.
- Преобразование UUID в DN-ключи при репликации может быть некорректным, из-за чего синхронизатор может удалить пересозданную запись либо перезаписать её последнее обновление старым значением.
- Устранение технических ошибок при формировании списка существующих записей (present list), которые приводят к полному или частичному удалению записей DIT:
- Может отправляться пустой present list без попыток его локального формирования, с последующим удалением всех записей на получателе репликации.
- Некорректная обработка ошибок при формировании present list приводит к его «обрезанию» и удалению всех упущенных записей на получателе репликации.
- Устранение недочёта в RFC-4533 при работе в режиме multi-master с тремя или более участниками. Есть эффект «экранирования удаления». Достаточно сложно и запутанно, но суть в том, что могут накапливаться записи, которые были удалены на одном сервере, но остались на других и уже никогда не будут удалены механизмом репликации/синхронизации. При этом обнаружить расхождение можно только «построчно», сравнив участвующие в репликации базы. Наше текущее решение сводится к дополнительной сверке данных — это не идеально, но обеспечивает совместимость с OpenLDAP и старыми версиями ReOpenLDAP, что крайне важно при промышленной эксплуатации. Подробности см. bit.ly/2d9z53B.
- Устранение логических ошибок в механизме репликации (синхронизации содержимого), которые приводят к потере отдельных изменений:
- Во-вторых, прочие важные переделки:
- Проверки с AddressSanitizer, ThreadSanitizer, PVS-Studio, Coverity.
- Поддержка TCP-keepalive для входящих соединений к серверу, в том числе к поставщику репликации (syncprov) при обслуживании persistent search запросов.
- Реализация «Recursive Upgradeable Read-Write Lock» с устранением ряда проблем в Config Backend.
- Много работы по устранению редких сбоев встроенных тестов.
- Слияние liblber и libldap, переход на актуальные версии Automake и Autoconf с переделкой сборки. Важно, что при этом существенно выросла готовность (прозрачность) проекта к CMake и другим инструментам.
- Импортированы все релевантные патчи от Red Hat, ALT Linux, Debian/Ubuntu.
- В-третьих, конечно, переносились все патчи из оригинальных OpenLDAP и LMDB, но порядка 20–30 % были неактуальны для ReOpenLDAP и MDBX (у нас уже исправлено).
Всего порядка 800 коммитов, из которых на портированные из OpenLDAP приходится менее 1/8.
Ближайшие задачи и планы
- Вопросы с лицензией
- Цель — переход на AGPL, как рабочий вариант — двойное лицензирование: исходная лицензия OpenLDAP плюс AGPL для всех наших доработок и добавлений. Сейчас мы пытаемся договориться с OpenLDAP Foundation, одновременно поняв, «как правильно». Советы и помощь приветствуются.
- Верификация в Coverity и PVS-Studio
- Проверка в Coverity выявила 444 «дефекта», см. scan.coverity.com/projects/reopen-reopenldap. Выглядит кошмарно, но на момент ответвления дефектов было почти в пять раз больше — поэтому на самом деле тут колоссальный прогресс. Среди этих «дефектов» основная часть — false positives, но их всё равно следует «погасить», а для этого требуется рафинирование многих функций в libreldap.
- Пакетирование
- К сожалению, эти задачи постоянно вытесняются более «пожарными». Поэтому тянем резину. Пока есть только сторонняя сборка rpm для Fedora/RHEL/CentOS.
- Устранение редких сбоев тестов
- Уже проделана огромная работа, в ходе которой выявлено и исправлено много «плавающих» ошибок. Но некоторые тесты всё-таки иногда сбоят, особенно при параллельном тестировании (высокая, но нерегулярная нагрузка, задержки из-за свопинга). Частично проблема в самих тестах, частично в ещё не выявленных ошибках.
- Сравнительные тесты
- Опыт, полученный при починке репликации в multi-master режиме, позволяет сделать обоснованное предположение, что в этом режиме из всех LDAP-серверов стабильно работает только наш ReOpenLDAP. Возникает желание проверить это предположение, одновременно оценив итоговую производительность.
Примечания и отзывы
Plays:236
Comments:1
