Недавно мы открыли для внешних пользователей Яндекс.Трекер – нашу систему управления задачами и процессами. В Яндексе его используют не только для создания сервисов, но даже для закупки печенья на кухни.  Как известно, чем меньше компания, тем более простые инструменты она может использовать. Если с утра вы можете поздороваться с каждым сотрудником лично, то вам хватит для работы даже чата в Telegram. Когда появляются отдельные команды, не только поприветствовать каждого лично не получится, но и в статусах задач можно запутаться.  
Облако из слов в заголовках тикетов во внутреннем Яндекс.Трекере На таком этапе важно сохранять прозрачность процессов: все стороны должны иметь возможность в любой момент узнать о ходе работы над задачей или, например, оставить свой комментарий, который не пропадёт в потоке рабочего чата. Для небольших команд трекер – это и вовсе своего рода новостная лента с последними новостями из жизни их компании. Сегодня мы расскажем читателям Хабрахабра, почему Яндекс решил создать свой трекер, как он устроен внутри, и с какими сложностями нам пришлось столкнуться, открывая его наружу. В Яндексе сейчас работает больше шести тысяч человек. Несмотря на то, что многие его части устроены как независимые стартапы со своими командами разного размера, необходимость понимать, что происходит у людей на соседнем этаже всегда есть – их работа может пересекаться с вашей, их улучшения могут помочь вам, а какие-то процессы наоборот могут негативно повлиять на ваши. В такой ситуации сложно, например, призывать коллегу из другого рабочего пространства в Slack. Особенно, когда прозрачность задачи важна для множества людей из разных направлений.  В какой-то момент мы начали использовать известную всем Джиру. Это хороший инструмент, функциональность которого в принципе всех устраивала, но его было сложно интегрировать с нашими внутренними сервисами. Кроме того, на масштабе в тысячи человек, которым нужно единое пространство, где каждый сможет сориентироваться без фонарика, Джиры переставало хватать. Случалось и такое, что она ложилась под нагрузкой, даже при том, что работала на наших серверах. Яндекс рос, количество тикетов также увеличивалось, а обновления на новые версии занимали всё больше времени (последний апгрейд занял полгода). Нужно было что-то менять. В конце 2011 года у нас было несколько вариантов решения проблемы: Разработка собственного трекера началась в январе 2012 года. Первой свои задачи в новый сервис перевезла сама команда трекера через несколько месяцев после начала работы над проектом. Дальше начался процесс переезда остальных команд. Каждая команда выдвигала свои требования к функциональности, их прорабатывали, трекер обрастал новыми фичами, затем перевозили команду. На полный переезд всех команд и закрытие Джиры понадобилось два года. Но давайте вернемся немного назад и посмотрим на список требований, который был составлен для нового сервиса: А ещё в момент сбора требований мы определились с теми технологиями, которые будем использовать для создания трекера: Как и для любых других публичных и внутренних сервисов Яндекса, нам пришлось также задуматься о требованиях к запасу производительности и масштабируемости сервиса. Пример для понимания ситуации. На момент начала проектирования системы у нас было порядка 1 млн задач и 3 тыс. пользователей. На сегодняшний день в сервисе почти 9 млн задач и более 6 тыс. пользователей. Кстати, несмотря на довольно приличное количество пользователей во внутреннем Трекере, бОльшая часть запросов приходит в трекер, через API от сервисов Яндекса, интегрированных с ним. Именно они и создают основную нагрузку:  Ниже можно увидеть перцентили ответов в середине рабочего дня:  Мы стараемся регулярно оценивать будущую нагрузку на сервис. Строим прогноз на 1-2 года, затем с помощью Лунапарка проверяем, что сервис ее выдержит:  На этом графике видно, что API поиска задач начинает отдавать заметное число ошибок лишь после 500-600 rps. Это позволило оценить, что с учетом роста нагрузки от внутренних клиентов и роста количества данных мы выдержим нагрузку через 2 года. Кроме высокой нагрузки с сервисом могут случаться и другие неприятные истории, с которыми надо уметь обращаться так, чтобы пользователи этого не замечали. Перечислим некоторые из них.  Отказ датацентра.
Весьма неприятная ситуация, которая тем не менее регулярно происходит благодаря учениям. Что происходит при этом? Худший случай, это когда мастер монги был в отключенном ДЦ. Но даже в этом случае не требуется вмешательство разработчика или админа благодаря автоматическому failover. В эластике ситуация немного иная: часть данных оказалась в единственном экземпляре т.к. фактор репликации у нас 1. Поэтому он создает новые шарды на уцелевших нодах, чтобы у всех шардов снова была резервная копия. Тем временем балансер над бекендом получает таймаут соединений в тех запросах, которые выполнялись на инстансах в отключенном ДЦ, либо ошибку от работающего бекенда, чей запрос ушел в пропавший ДЦ и не вернулся. В зависимости от обстоятельств, балансер может попытаться повторить запрос или вернуть ошибку пользователю. Но в итоге балансер поймет, что инстансы из отключенного ДЦ ему недоступны и перестанет отправлять туда запросы, проверяя в фоне, не заработал ли все-таки ДЦ и не пора ли возвращать туда нагрузку. Потеря связности между бекендом и базой/индексом из-за проблем с сетью.
Чуть более простая ситуация на первый взгляд. Так как балансер над бекендом регулярно проверяет его состояние, то ситуация, когда бекенд не может достучаться до базы всплывает весьма быстро. И балансер опять уводит нагрузку с этого бекенда. Есть опасность, что если все бекенды потеряют связь с базой, то их всех же закроют, что в итоге повлияет на 100% запросов. Высокая нагрузка запросов в поиск трекера.
Поиск по задачам, их фильтрация, сортировка и агрегация – весьма трудозатратные операции. Поэтому именно эта часть API имеет самые строгие лимиты по нагрузке. Раньше мы находили вручную тех, кто заваливал нас запросами и просили их сбавить нагрузку. Сейчас такое происходит всё чаще, поэтому включение rate limits позволило не замечать излишне активного клиента API. Нашими сервисом не раз интересовались другие компании – они узнавали о нашем внутреннем инструменте от тех, кто покидал Яндекс, но не мог забыть Трекер. И вот в прошлом году внутри мы решили готовить Трекер к выходу в мир – делать из него продукт для других компаний.
Мы сразу начали прорабатывать архитектуру. Перед нами встала большая задача по масштабированию сервиса до сотен тысяч организаций. До этого сервис годами разрабатывался для одной нашей компании, учитывал только её потребности и нюансы. Стало ясно, что текущая архитектура потребует сильных доработок. В итоге у нас было два варианта решения.  Очевидно, что стабильность сервиса для внешних пользователей не менее важна, чем для внутренних, поэтому необходимо дублировать базы, поиск, бэкенд и фронтенд в нескольких датацентрах. Это делало первый вариант гораздо более сложным в обслуживании – получалось много точек отказа. Поэтому конечным вариантом мы выбрали второй.  Переписывание основной части проекта у нас заняло два месяца, для такой задачи это были рекордные сроки. Тем не менее, чтобы не ждать, мы подняли несколько копий трекера на выделенном железе, чтобы было на чём тестировать фронтенд и взаимодействие со смежными сервисами. Отдельно стоит отметить, что еще на этапе проектирования, мы приняли принципиальное решение сохранить одну кодовую базу для обоих Трекеров: внутреннего и внешнего. Это позволяет не заниматься копированием кода из одного проекта в другой, не снижать скорость релизов и выпускать возможности наружу почти сразу после их появления в нашем внутреннем Трекере. Но как выяснилось, мало было добавить ещё один параметр во все методы приложения, мы также столкнулись со следующими проблемами: Отдельный момент – оценка производительности. Из-за множества переделок необходимо было оценить скорость работы, количество организаций, которое бы вместилось в инстанс, а также поддерживаемый rps. Поэтому мы провели очередные стрельбы, предварительно заселив в наш тестовый трекер большое количество организаций. По итогам определили границу нагрузки, после которой новые организации надо будет размещать в новом инстансе.  Еще один специальный выделенный инстанс Трекера мы сделали, чтобы разместить в нем демоверсию. Чтобы попасть в нее достаточно иметь просто аккаунт на Яндексе. В ней заблокированы некоторые возможности (например, загрузка файлов), но зато можно познакомиться с настоящим интерфейсом Трекера. Разработчик