Никита Галушко, разработчик подразделения Online Shop Lamoda, в онлайн-гостях у учебного центра Слёрм поделился своими впечатлениями от курса по Kafka, рассказал, как используют эту технологию и какие проблемы решают в отделе R&D (Research and Development).

«Как быстро мы упремся в сетевой канал, который использует Kafka — через года два или раньше?»

Lamoda — один из крупнейших интернет-магазинов в России и СНГ. Чтобы покупатели пользовались сайтом без проблем и радовались быстрой отгрузке и доставке, IT-системами в Lamoda занимаются 340 сотрудников: разработчики, QA-инженеры, аналитики, DevOps-специалисты, продуктовые менеджеры, дизайнеры. Узнаем, как в этой системе крутятся винтики.

Расскажи немного о себе. Чем ты занимаешься в Lamoda и сколько уже там работаешь?

Как я люблю говорить: «Я нажимаю на кнопки, и мне за это платят деньги». Нажимаю я на кнопки уже лет шесть. Все это время я пишу на Go. В Lamoda я не так давно, с октября 2020 года, но успел уже выпустить свои щупальца во многие сервисные проекты.

Я работаю в отделе RnD (Research and Development) — это отдел, где на одной неделе ты пишешь сервис на Kafka и решаешь вопрос, как сделать распределенную транзакцию между Kafka и PostgreSQL, а на следующей пишешь кодогенератор для Aerospike. Это очень интересная работа.

Я правильно понимаю, что R&D сильно подвязан под аналитику?

Да, мы работаем в тесной связке с дата-сайентистами. Они проводят аналитику, обучают и строят модели, а потом приходят к нам с запросом встроить эти модели в работу приложения или сайта. Например, модель, которая показывает пользователям персонализированный список рекомендаций или подсказывает, какой размер одежды или обуви, скорее всего, подойдет покупателю.

А что из задач тебе нравится в работе? Что для тебя в отделе R&D интересного?

Наверное, это свобода. Ты не ограничен каким-то одним доменом знаний, сервисом или небольшим набором сервисов. В R&D ты можешь делать изменения в сервисе на Go, а на следующий день — изменение на Java. Для кого-то, возможно, это недостаток, так как при таком подходе сложно сфокусироваться на одном сервисе. Но для меня это возможность попробовать свои силы в разных областях, посмотреть, какие подходы разработчики использовали для решения разных задач, почерпнуть для себя что-то новое.

Мы совсем недавно начали делать кодогенератор для парсинга результатов работы Aerospike. Так как он отдает сырые данные, то постоянно приходится разбирать их руками. А это потенциальные ошибки и трата драгоценного времени: ты что-то забыл или не проверил, и выходит не тот результат, который ожидаешь. Поэтому мы подумали и решили написать свой кодогенератор. Пока он работает в тестовом режиме, но я надеюсь, что в скором времени мы его заопенсорсим.

А Lamoda часто делает опенсорс-проекты?

У Lamoda есть относительно известный опенсорс-проект Gonkey. Подробнее о нем можно почитать в нашей статье.

Gonkey — это стандартизированный набор решений, который позволяет легко писать автотесты на языке разметки Yaml. Это удобно тем, что такие тесты могут писать как разработчики, так и тестировщики, тем самым увеличивая процент покрытия тестами.

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

Скорее всего, для этого надо обладать широким стэком знаний, учиться в два раза больше чем обычно. Так ли это?

Я бы сказал, что надо просто обладать широким кругозором.

Поверхностно?

Не совсем так. Есть такое понятие, как T-shape разработчик. Он очень хорошо, даже отлично, понимает в какой-то одной области, но при этом более или менее разбирается еще в ряде других областей. Я уже сказал, что сейчас пишу на Java, но все же 99% кода я пишу на Go. Поэтому, когда ты очень хорошо знаешь Go-шный стек и при этом умеешь смотреть по сторонам, это хорошо не только при работе в R&D, но и в целом. Ты можешь почерпнуть какие-то идеи и подходы из других технологий и языков.

Я знаю людей, которые какое-то время писали на Python, а потом перешли на Go — им понравилось, как этот язык подходит к обработке ошибок. Теперь они пытаются привнести такой же подход и в те проекты, которые пишут на Python.

Наверное, у каждого разработчика, который хочет развиваться, нет другого выбора — нужно прокачиваться в разных областях. Вечно сидеть разбираться только в одной узкоспециализированной области у тебя не получится. Если ты хоть где-то работаешь, то нужно развиваться.

Как я понимаю, задачи в R&D разноплановые. Приходилось ли тебе что-то изучать в процессе?

Обучение и развитие со мной, с тех пор как я познакомился с программированием в 10 классе лицея. Я получаю удовольствие, когда узнаю что-то новое или когда о чем-то новом рассказываю остальным. До Lamoda я работал во ВКонтакте и точно так же развивался, читал статьи, проходил курсы, смотрел выступления с конференций.

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

Если говорить про работу в Lamoda, то что тебе понадобилось прокачать за последний год, кроме Kafka?

Работа с Kubernetes и написание helm-чартов. Кстати, проходил курс по Kubernetes у вас, потому что до этого я с ним не работал. Обычно это были либо виртуалки, либо физические железки, и все проходило либо через админов, либо ты сам имел доступ, чтобы выкатить deb-пакет. Поэтому пришлось освоить Kubernetes: не на уровне «через kubectl посмотреть состояние pod-a», а на уровне правильного написания helm-чарта и понимания, как оно работает внутри.

Раз уж заговорили о курсах, давай поговорим о Kafka. Зачем ты пошел на курс по Kafka?

Я увидел на сайте баннер: «Скоро курс по Kafka». И подумал: «Надо идти!»

Как я уже упоминал, я просто люблю познавать что-то новое. Не надо быть семи пядей во лбу, чтобы на минимальном уровне отправить или прочитать сообщение в Kafka. Но в целом в Lamoda Kafka используется давно и прочно. Поэтому глубокое погружение в эту технологию было для меня неизбежным.

А что для тебя Kafka?

Для меня это распределенный, отказоустойчивый лог с простым интерфейсом взаимодействия, который может прокачать через себя невероятно большой объем данных.

Как Kafka применяется в Lamoda?

Мне кажется, что найти сервис, который не использует как-то Kafka в Lamoda очень сложно. На ней у нас реализован event-bus — это такая шина событий всей Lamoda. Кто-то пишет какие-то события, и любой другой участник, который подсоединен к этой шине, может читать их и как-то на них реагировать.

Если говорить про новые проекты, то недавно мы запустили сервис по сбору аналитических данных с бекендов xlog (это его внутреннее название). Тоже через Kafka, так как там требуется высокая пропускная способность всей системы.

Еще Kafka нужна для работы с ClickHouse, в котором есть Kafka-engine. То есть мы просто пишем в Kafka, а ClickHouse считывает и записывает к себе данные. Это очень удобно, потому что мы работаем над одним из проектов, где записи в ClickHouse надо делать много и часто. И как мы знаем, ClickHouse не умеет этого делать хорошо из коробки — ему нужен подходящий прокси. Сейчас на рынке есть решение от Яндекса и ВКонтакте, но так как в Lamoda и так хорошая экспертиза в Kafka, мы решили использовать именно ее для связи с ClickHouse.

Также мы активно ее используем для разного рода аналитики.

А как команда R&D использует Kafka? Если ты говоришь, что Kafka для тебя — это логи, правильно ли я понимаю, что ты разрабатываешь с помощью нее сервисы, то есть ты работаешь с Kafka Streams?

У нас есть своя обертка над библиотекой по работе с Kafka, которая дает некую абстракцию. А по факту в Go есть каналы: разработчики читают из канала и пишут туда. Они могут даже не задумываться о том, Kafka это или нет.

С какими проблемами в работе с Kafka сталкивался ты и твоя команда? Как пытались их решать?

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

Условно тот же сервис по сбору аналитических данных — первый кандидат на сжатие. Но мы же не можем просто взять и включить сжатие, потому что это некоторый trade-off между использованием CPU на продьюсерах и консьюмерах.

Сейчас я пытаюсь подготовить документ с тестами и анализом. Кстати, в этом мне очень хорошо помог ваш курс, потому что там есть отдельный урок, как бенчмаркать Kafka. В этом документе я хочу отразить, есть ли сейчас необходимость включать на этот сервис компрессию. Если да, то какую именно включать, ведь есть разные алгоритмы сжатия. Мне кажется, это самая явная тема для улучшений.

А текущих горящих проблем с Kafka нет?

Когда мы настраивали работу ClickHouse с Kafka, была проблема в том, что права на describe в группе, которую мы использовали, были выставлены не совсем правильно.

Это выглядит менее страшно, чем план упереться в пропускную способность.

Спрошу тебя и о том, что я недавно узнал. С версии Kafka 2.8 вышел KIP500 по отказу от ZooKeeper. И я так понимаю, что Kafka упиралась в наличие ZooKeeper, его ограничения. Обещают, что при отказе от ZooKeeper количество партиций увеличится до двух миллионов. Это как-то решает вашу проблему?

Если отвечать прямо, то нет, не решает, потому что мы упираемся не в работу Kafka, а в тот сетевой канал, который мы используем до нее. Она легко справляется с тем объемом данных, который мы на нее шлем — канал от этого не меняется.

Если говорить про KIP500, то там сделали первый шаг к отказу от ZooKeeper, Но пока это не выглядит надежным решением: резко отказываться от ZooKeeper и переходить на 2.8, наверное, все же не стоит для каких-то более или менее нагруженных продакшен-систем.

Тут еще дело в том, что обычно с Kafka имеют дело ops`ы, и им надо понимать, как решать возникающие проблемы. Сейчас они знают: если что-то случилось, им надо пойти сделать что-то определенное в Kafka, а в ZooKeeper — что-то другое. А когда его нет, план по решению проблем не работает, и придется наработать экспертизу в этом вопросе.

Я верно понял: вы упираетесь в сеть и горизонтальное масштабирование Kafka не помогает, то есть это проблема только сети?

В целом Kafka сделана так, что ты будешь упираться в сеть или во что-то другое, но не в ее производительность. Я точно помню, что на курсе об этом говорится, и преподаватели подробно объясняют, почему так. Но мы об этом говорить не будем, чтобы те, кому интересно, пошли смотреть курс.

По большой задаче все понятно — пропускная способность. И для решения этой задачи ты пошел на курс, чтобы ее погрумить и принести что-то в команду. Это совпадение или осознанно вышло?

Совпадение, потому что я изначально пошел смотреть курс, чтобы не просто узнать, как писать в Kafka. Ведь для хорошей и правильной репликации нужно выставлять правильный acks. Курс погружает тебя во внутренности системы и то, как она работает.

Если мы говорим про курс, то там нет разделения на разработчиков и админов. Ты проходил все темы или админские пролистывал?

Я проходил все темы, потому что мне все интересно. Я получаю кайф от того, что узнаю новое. Обычно я конспектирую, а через какое-то время я возвращаюсь к этим конспектам, перечитываю, что-то выбрасываю. Если что-то неясно, иду пересматриваю часть курса и переписываю часть конспекта.

А практику ты проходил? Тебе было тяжело их выполнять, особенно те, что админские?

Я прошел, но пока не все. Нет, там было все достаточно хорошо расписано, как и что нужно сделать и какой результат ожидать. Мне было интересно.

В начале используется приложение на Java для некоторых практических работ. Мне было интересно не просто выполнить эту работу, а я потратил какое-то время на изучение кода в Java, который работает с Kafka. Надо смотреть чуть глубже и шире, когда ты проходишь такие практические задания.

То есть ты смотришь на технологию.

Да. Я когда делал работу по партициям — там было про репликацию. И я подумал, а что будет, если я сделаю несколько иначе. Я потратил время, чтобы поиграться и проверить, что будет, если я выключу одну ноду? А если две? А если я еще что-нибудь сделаю? Это хорошо, что есть стенд для практики, тебе не надо поднимать у себя ничего. На это не надо тратить время.

Расскажи, что тебе было интереснее всего? О чем таком ты узнал, чему сильно удивился?

Например, что по факту Kafka — это in-memory очередь. Мы привыкли, что базы данных не просто пишут на диск, а еще вызывают fsync, чтобы операционная система сбросила данные на диск. Потому что просто позвать write не гарантирует, что данные запишутся.

Kafka этого не делает: она просто зовет write, системный вызов, и все. Просто говорит: «Ты операционная система, ты сама реши, когда это сбросить». И по факту надежность Kafka обеспечивается за счет репликации. Я этого не знал. Я думал, что Kafka вызывает fsync и честно персистит все данные на диск. Вот какая она хитрая.

Еще было интересно послушать про проблемы нескольких датацентров.

Твои задачи по пропускной способности. Что у тебя получилось вынести с курса для решения будущих задач?

То, как измерять работу Kafka, и то, как она работает со сжатыми данными. Kafka не разжимает их у себя, а пишет их на диск и как есть отдает потребителям. Это дало понимание, что надо смотреть на затраты на CPU не только на продюсере, который пишет в Kafka, но и на консьюмере, который читает из нее. Ну, и как это правильно бенчмаркать.

А может, было что-то сложное в курсе для тебя? Или какая-то практика была особенно сложная?

Такое точно было: какое-то видео я пересматривал несколько раз. Точно пересматривал про ребалансировку консьюмер-группы. С первого просмотра было не совсем понятно, как это происходит. Я говорю не про простую ребалансировку, а про инкрементальную. Это пришлось пересмотреть и перечитать.

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

И в заключение спрошу: что у тебя в планах по обучению и работе?

Я начал вести свой блог. Купил домен и бесплатно поднял его на DigitalOcean — они бесплатно раздают статику. Блог дает мне стимул что-то узнавать, записывать и делиться этим с остальными. Ты понял тему тогда, когда можешь это рассказать кому-то, чтобы он тоже понял.

И блог как раз дает навык пересказывания. Сейчас разбираюсь с эффективностью работы GIN индексов. Скоро будет статья на эту тему, которая основана на прошлогоднем выступлении на GolangConf.

Всегда нужно смотреть по себе: если есть силы, то почему бы не почитать статью, как устроен Go.