Переход Почты Mail.Ru на 64-битную архитектуру: как это было

    Уже несколько месяцев, как фронты Почты Mail.Ru стали 64битными. Лучше поздно, чем никогда, решили мы, и сегодня я расскажу, зачем мы это сделали, через что мы ради этого прошли и как нам это удалось.



    И так работает

    Долгое время наша Почта работала на 32 битах на первом Apache и Perl 5.8 под управлением CentOS 5. Идея перевести фронтенд на более современное ПО и 64-битную архитектуру бродила в наших умах давно: еще полтора года назад всего два человека — один админ и один разработчик — за какую-то неделю без сна подняли тестовый сервер, на котором крутилось наше светлое будущее. Однако в те времена у нас были более срочные задачи, и про сервер благополучно забыли. Периодически к этой идее возвращались, но все происходило в режиме «А что если так? — Ой, что-то сломалось!», — и снова все откатывалось и откладывалось в долгий ящик.

    Time has come

    Наконец пришло время перемен. В какой-то момент мы осознали, что дальше так продолжаться не может: полная поддержка CentOS 5 прекращается в 2014 году, Perl 5.10 на некоторых задачах показывает 30% прирост скорости, не говоря уже о том, что 32-битная архитектура в XXI веке несколько отстает от желаемого.
    Кроме того, после того как мы перевели Почту на HTTPS, на фронтендовых серверах повысился load average, так что более производительный Perl стал актуальным как никогда.

    Трудности перехода

    Прежде всего, нам пришлось разово переписать те места кода, которые непосредственно взаимодействуют с Apache. Так как на ErrorLog Apache завязана наша система мониторинга, пришлось научить новый сервер логировать ошибки так, как нам нужно. В результате появился самописный модуль для логирования ошибок Apache 2, доступный по ссылке.
    Кроме того, пришлось разбираться с зависимостями: все используемые нами пакеты исторически собирались под c5x32 архитектуру и в таком виде складывались в репозиторий. В изменившихся реалиях все, включая модули под nginx, пришлось пересобирать для c6x64.
    Также был полностью переписан модуль генерации капчи.
    Однако больше всего хлопот нам доставили баннеры. Вся наша верстка построена на слотах, содержимое которых, в том числе и баннеры, берется из шаблонизатора, написанного на С и глубоко интегрированного в Apache. Модуль, отвечающий за баннеры, подхватывает заголовки Apache и по ним уже таргетируется. Чтобы заставить все это взлететь под Apache 2, пришлось не только потрудится самим, но и раскачать ребят из соответствующего отдела.

    Бинарные протоколы

    В Почте Mail.Ru взаимодействие часто происходит через бинарные протоколы. Прежде всего, это общение с нашим хранилищем данных Tarantool. Помимо базы, даже между нашими сервисами, например, сервером на Perl и сервером на C, данные передаются в бинарном виде. Это хорошо, быстро и удобно, пока речь не заходит о смене архитектуры.
    Каждый раз, когда необходимо шифровать данные или складывать по модулю, вероятность того, что результаты выполнения операции на x32 и x64 будут разными, становится ненулевой. Осложняется все тем, что эти различия проявляются только на специфических данных, так что искать, отлавливать и фиксить эти случаи — задача нетривиальная.
    Например, первая строчка кода, приведенного ниже, отработает на разных архитектурах совершенно по-разному.
    my $crypted_userid = $user->{'ID'} ^ 41262125215;
    getpage('project_url_api?user_id='.$crypted_userid);
    Эта разница поведения приводит к проблемам в совершенно неожиданных местах и даже на разных проектах. Например, новые результаты выполнения кода с айдшником пользователя приводили к тому, что благодаря нашей общей системе авторизации смена пароля одним пользователем влекла за собой разлогинивание совершенно другого пользователя из другого сервиса.
    Эта же проблема с шифрованием обнаружилась и в самой Почте. После отправки письма пользователь отправляется по URL, который, среди прочего, содержит зашифрованных получателей (никто ведь не хочет, чтобы его email передавался в адресную строку в открытом виде). Что случилось после того, как мы стали формировать URL на 64-битной архитектуре, догадаться несложно: вместо списка получателей появлялся случайный набор символов.
    Конечно, сейчас эти проблемы решены, но их отлавливание заняло существенное время.

    Всего по два

    Сам переход уложился в два месяца. До того как это произошло, около полугода наша Почта работала как на старых фронтах, так и на новых. Мы тщательно мониторили поведение этих двух систем: на нашем дашборде было два отдельных графика, по которым мы следили, где больше ошибок и что работает быстрее. С ними связана забавная история — однажды посреди ночи всех подняли на уши, потому что на графиках перфоманса у новых фронтов линии проходили выше — выходило, что они отрабатывают существенно медленнее. Потом, правда, выяснилось, что это мы настолько наоптимизировались, что шкала для новых фронтов автоматически изменилась на порядок, и на самом деле они отрабатывают в 10 раз быстрее. Тем не менее, перепугаться мы успели.
    Кроме того, в условиях двух систем нельзя просто так взять и обработать реквест Apache. Приходится делать следующее:
    sub GetApacheRequest {
    $ENV{MOD_PERL} =~ m{mod_perl/2}? Apache2::RequestUtil->request(): Apache->request();
    }
    Сборка пакетов для Почты также стала пестрить условиями вида
    %if 0%{?centos} == 6

    %if 0%{?centos} == 5

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

    Награда за труды

    Итак, что же мы получили в результате этой кропотливой и иногда нервной работы?
    • Полная поддержка CentOS 6 — новые патчи, актуальное состояние системы
    • Быстрые регулярки в Perl 5.10. Скрипты, выполняющие анализ и парсинг, летают еще быстрее
    • Apache 2 подхватывает новый конфиг и скрипты без рестарта. Выкладка кода и конфигов не приводит к 500-й ошибке (теоретически это умел и первый Apache, однако заставить его делать это нормально без отключения фронта от нагрузки — задача из области фантастики)
    • Тотальный рефакторинг. Переход на новое ПО — прекрасный повод избавиться от лишних зависимостей, ненужных сущностей и неиспользуемых модулей
    • Использование Puppet. Гулять так гулять, решили мы, и заодно перешли на Puppet. Теперь раскладка новых фич и деплой хотфиксов стали существенно проще.

    Следовало ожидать, что переход с 32 на 64 бита пагубно скажется на потреблении памяти Apache, который и без того пытается отъесть все, что дадут. Количество памяти, выделяемой под один процесс, разумеется, выросло, от этого никуда не деться. Однако все стало работать быстрее, поэтому с задачами справляется меньшее число процессов, так что в целом затраты по памяти не выросли. Кругом профит.
    Perl 5.10, кстати, дает нам дополнительное преимущество: простоту перехода на 5.16 по сравнению с мучительным переходом с 5.8.8. Так что ждите новый Perl в нашей Почте.
    Если у вас появились вопросы, предлагаю обсудить их в комментариях.

    Илья Зарецкий,
    руководитель группы backend разработки Почты
    Mail.ru Group
    Building the Internet

    Similar posts

    Comments 46

      +1
      Не знал, что почта у вас на перле работает. С чем это, кстати связано? Исторически или есть какие-то преимущества по сравнению с питоном, например? Еще вопрос — вы deamon tools используете или что-то еще?
        +2
        Причины исторические
          +1
          А как вообще, работой с Perl довольны? Нет ли желания мигрировать на другой язык? Если есть, то какие основные преимущества других языков видите? Если нет — то хорошо :)
            +6
            Мы вполне довольны перлом. Есть свои нюансы.
            Преимуществ у языков разных множество, на каждом можно написать высокопроизводительные и качественные продукты.

            У нас есть продкуты которые с нуля написаны на перле за последний год. Есть также и на питоне. Каждый тимлид хвалит свой язык и им доволен.
              0
              Из крупных компаний очень многие используют perl, не только для админки.

              А если инет компания ещё и относительно старая, то у неё будет perl в 99,9%

          +1
          Еще вопрос есть про бинарные протоколы — у вас свой велосипед или что-то подобное google protobuf/Thrift?
            +3
            Свеой велосипед, которому местами 15 лет
          • UFO just landed and posted this here
              +12
              не, там же центось, так что скорее наоборот — Корзина и Корзина64.
                –11
                Видимо чтоб была нативная поддержка iPhone 5S
                0
                Нет, «Входящие» и «Входящие (UTF-16)». Гулять, так гулять! =)
                +2
                по сравнению с мучительным переходом с 5.8.8.

                А какие были проблемы с 5.8.8 на 5.10? Не связанные с 32bit vs 64 bit?

                my $crypted_userid = $user->{'ID'} ^ 41262125215;


                если о существовании кода с побитывыми операциями, кода использующего use integer и кода, работающего с числами больше 2**31, 2**32, или 2**53 было известно до миграции, то можно было просто написать интеграционные тесты, тупо проверив md5 результата для диапазона чисел, и внеся ожидаемый результат как фикстуру в тест.

                по крайней мере так делаю в своём коде — никаких проблем не имею. пишут тест для каждой подозрительной строчки.

                можно тестировать псевдослучайными числами (взять 100_000 числел) только последовательность должна быть одна и та же всегда.

                perl -MDigest::MD5=md5_hex -e'print md5_hex(join(",", map { $_ ^ 41262125215 } map { $_ - 1, $_ + 1, $_ - 100, $_ + 100 } map { 2**$_ } map { $_, $_ -1 } (32, 53)))'
                
                


                perl-5.8.8-64int
                ==========
                bb45f30d7271d4e70f8ea43240215e69
                
                perl-5.8.8
                ==========
                d28324accda448de64f77fd2d8739140
                
                
                
                  +23
                  Когда я увидел, что в моем первом почтовом ящике mail.ru была уничтожена вся переписка старше нескольких лет, включающая милейшие письма типа переписки с первым работадателем, и другие памятные моменты, я был в полнейшем шоке. Второе десятилетие 21 века… Как?! А потом узнал, что почту в двух других моих ящиках, куда не заходил год, убили под чистую.

                  Рад, что внедряете российскую изюммнку в современные сервисы. Всяческих успехов и лучей добра вам!!!
                    0
                    А нескольких это сколько? Чекнул свои ящики, всё в сохранности.
                      +1
                      Это около года назад случилось. Сейчас просто воспользовался возможностью высказать благодарность представителям компании.
                    –5
                    За лучи спасибо, конечно.

                    Мы действительно удаляем письма из ящика, если он не используется в течении длительного времени (в него нету заходов, с него не забирается почта).
                      +1
                      Эм, а как быть с массивом переписки на основных ящиках? Ну скажите, что я просто не заметил папку «Архив», где они все благополучно складированы…

                      И посоветуйте, как часто нужно заходить на почту, чтобы ящик не удалили?
                        –3
                        Так, стоп. Почта цела на основном. Видимо был глюк, тогда менялся итерфейс ящика и листалка заканчивалась где-то на 2007 году. Мои извинения.
                          +8
                          Добавлю вам за это своих лучей.
                          +14
                          Подходил к концу 2013 год…
                            0
                            Лучше поздно, чем никогда.
                            Хоть сам уже не пользуюсь почтой от mail.ru, но искренне рад их апгрейду.
                            +4
                            Планируется ли изменение бизнес-модели почты mail.ru с заработка на спаме на другие способы монетизации?
                              +4
                              А чем обусловлен выбор именно 5.10? Он точно так же снят с поддержки много лет назад как и 5.8. Почему не мигрировали на 5.14 или 5.16, глобальных проблем миграции, по сравнению с 5.10, там не должно было добавиться.
                                +1
                                Я думаю тем что он в CentOS6 и поддерживается RHEL (по крайней мере они должны делать security фиксы, а так же изредка портируют куски кода из остальных версий perl, что делает его не совсем 5.10).

                                Можно было и сразу на 5.18, только лучше же маленькими шажками.
                                Опять же можно было ещё уменьшить шаг и попробовать 5.8.8 64bit (только обязательно из CentOS5, ведь это фактически не 5.8.8 а нечто среднее между 5.8.8 и 5.8.9)
                                –4
                                полная поддержка CentOS 5 прекращается в 2014 году

                                So wut? Веб-фронтенды не торчат голым апачем наружу (к слову, разве первый апач не перешел уже в неподдерживаемые пакеты, собираемые вручную давным-давно?), поэтому практически все проблемы ядра не беспокоят, апач уже самосборный, про перл см ниже.
                                Perl 5.10 на некоторых задачах показывает 30% прирост скорости

                                Опять-таки, если это так важно, то можно организовать свой репозиторий с нужной версией perl.
                                32-битная архитектура в XXI веке несколько отстает от желаемого

                                Отстает от чего? Конечно, для всяких кешей вроде memcached неплохо иметь возможность адресовать более 3гб с процесса, но таких процессов можно запустить несколько — заодно и ядра простаивать не будут.
                                Apache 2

                                Неужели жизнь на apache 1.x из собственных репозиториев была бы сложнее, чем переписывание кучи все, завязанного на этот самый первый апач?

                                Ну и самый главный вопрос: зачем на веб-фронтах 64 бита, когда можно поставить 32-битную систему, или хотя бы 32-битные perl и apache2? Адресовать огромные объемы памяти на фронтах реально ни к чему, баги связанные с размерностью целых числе в перле не пришлось бы огребать, потребление памяти было бы чуть ниже при неизменной скорости работы?

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

                                  фикс этих багов является ликвидацией технического долга же, что же в этом плохого.
                                  0
                                  полная поддержка CentOS 5 прекращается в 2014 году

                                  Кстати всё же в 2017 году wiki.centos.org/FAQ/General#head-fe8a0be91ee3e7dea812e8694491e1dde5b75e6d и RHEL5 и CentOS5, а платная RHEL5 в 2020
                                    –5
                                    Статья претендует на самое скучное из всех возможных названий, что подтверждается фактом полного отсутствия кода. Где код?!?
                                      +6
                                      Вот он:
                                        +1
                                        «И таких мест масса.» :D
                                      +4
                                      Ха, perl. Молодцы. Значит, мы не одни такие, это радует =)
                                      У самого порядка 50 сервисов различной степени сложности, всё размазано по ~ 30 серверам… Где-то год назад ушли от использования системного перла, собираем свой, в отдельную папочку, там же все нужные либы, и свои пакеты, и пр. Зато теперь никакое обновление ОС не затронет работу наших скриптов.
                                      Мы даже опакетили вспомогательное ПО — lighttpd, redis, и тп. Теперь почти любой наш внутренний сервис можно поднять практически одной командой yum из своего репозитория — всё необходимое, скрипты и либы поставятся по зависимостям :]
                                        –1
                                        [lol]
                                        Mail Guard и прочие Mail *** теперь тоже работают только на x64?
                                        [/lol]
                                          0
                                          Не за горами CentOS 7, есть ли планы насчёт него?
                                            0
                                            Да вы что, тут коечто позначительней случилось — почта на км.ру перешла на веб 2,0 интерфейс. Вот событие — я думал ети ребята навечно застряли в епохе первого веба, аннет — ни шатко ни валко — а обновили.
                                              0
                                              А чем пользовались до пупета, cfengine?
                                                0
                                                А подстроку в строке обязательно регэкспом искать? Функция index недостаточно хороша?
                                                  +1
                                                  А зачем index? Регэксп недостаточно хорош?
                                                    0
                                                    Скорость же.
                                                      0
                                                      Разница в скорости меньше 10%, проигрыш в скорости ничтожен по сравнению с любой операций ввода-вывода.

                                                      В таком коде подавляющее большинство использует регэксп, он понятнее выглядит, его легче модифицировать если что-то понадобится изменить в коде.
                                                        0
                                                        Писать index вместо регекспа там, где это возможно — хорошая привычка.
                                                        P.S.: только что померил и получил разницу в 28%.
                                                          +1
                                                          наоборот, плохая привычка.

                                                          а по поводу бенчмарка, 10% максимум.
                                                          use warnings;
                                                          use strict;
                                                          
                                                          my $text = 'hello world';
                                                          
                                                          sub index_find {
                                                          my $x;
                                                          for (1..100) {
                                                          $x = index($text, 'world') >= 0;
                                                          }
                                                          }
                                                          
                                                          sub regex_find {
                                                          my $x;
                                                          for (1..100) {
                                                          $x = $text =~ /world/;
                                                          }
                                                          }
                                                          
                                                          use Benchmark qw( cmpthese );
                                                          
                                                          cmpthese -1, {
                                                          'index' => \&index_find,
                                                          'regex' => \®ex_find,
                                                          };
                                                          
                                                          
                                                          
                                                            –1
                                                            Во-первых, плохая привычка — это делать неаргументированные возражения.

                                                            Во-вторых, даже по вашему тесту вот такой результат:
                                                            Rate regex index
                                                            regex 49321/s — -13%
                                                            index 56888/s 15% — В-третьих, даже 10% совсем не лишние.
                                                  –2
                                                  Хорошая попытка, но всё равно нет, спасибо
                                                    –1
                                                    Данная попытка, кстати, какая-то вобще ни о чем.
                                                    –1
                                                    Раз это крайняя запись, посвященная почте, то спрошу здесь. Известно ли что-нибудь о реализации трехколоночного веб-интерфейса, наподобие того, что у «Яндекс.Почты» или Gmail?
                                                      +1
                                                      Коллеги, переход на x64 Вашей почты — это здорово. Но лучше бы Вы сделали корректной работу своих анти-спам фильтров + оперативной и качественной работу Вашей поддержки по abuse@. Это Вашим клиентам и коллегам по цеху было бы куда полезнее, чем переход на x64.

                                                      Я представляю сервис рассылок Smartresponder.ru и мы в числе самых крупных отправщиков почты в Рунете. Сейчас у нас 60% рассылок уходит на адреса Mail.ru. В прошлом году в середине Января Mail.ru заблокировало полностью все наши отправляющие рассылки сервера, а теперь уже в новом 2014 году в тот же период — Ваш антиспам отдел снова повторил бан большей части наших отправляющих серверов.

                                                      Учитывая тот факт, что мы соблюдаем все Ваши правила для массовых рассылок, знаем их уже наизусть, постоянно следим за нашей репутацией (нажатия на «спам» через postmaster, sender score), то такие Ваши действия просто обескураживают и наводят на печальные мысли о происходящем в отделе антиспама Mail.ru.

                                                      Примите пожалуйста меры по этой ситуации.

                                                      Все описано в тикете к Вам в abuse@ - Ticket#2014010921040847

                                                      Only users with full accounts can post comments. Log in, please.