ym104432846
Вставьте ссылку на видео из Youtube, Rutube, VK видео
Задайте вопрос по видео
Что вас интересует?
00:00:14
Описание мобильного приложения и команды разработки:
  • Приложение состоит из множества микросервисов, включая чистые back-end команды.
  • Команда разрабатывает финансовые результаты клиентов (графики, статистика, аналитика).
  • Используется legacy-решение, которое постепенно переписывается командой с нуля.
  • Состав команды включает middle-разработчика, двух искомых сотрудников (middle и senior), аналитика, методолога, тимлида и специалиста по автоматизации тестирования.
  • Применяются технологии .NET, PostgreSQL, RabbitMQ, Kafka, MongoDB, Redis, Docker, Kubernetes, GitLab CI/CD.
00:02:49
Опыт кандидата в разработке медицинских информационных систем:
  • Кандидат ранее участвовал в проекте реестра электронных медицинских документов.
  • Проект включал интеграцию документов из пяти российских регионов и внутренних сервисов компании.
  • Команда проекта насчитывала около 15-16 сервисов и примерно столько же команд.
  • Команды состояли из 7 человек, включая тимлида, front-end разработчика, системного аналитика и остальных back-end разработчиков.
  • Основные задачи включали закрытие технического долга и поддержку интеграции с внутренними и внешними сервисами.
00:03:55
Работа с техническими долгами:
  • Техдолг возник вследствие срочных релизов и необходимости быстрого внедрения функционала.
  • Часто встречалось выражение "сделайте сейчас, позже исправим".
  • Основной причиной накопления долгов стали сжатые сроки и давление заказчиков.
00:05:12
Использование брокеров сообщений и ORM:
  • Опыт работы с RabbitMQ, MassTransit, Apache Kafka и Entity Framework.
  • Применение ORM для упрощения взаимодействия с базой данных.
  • Использование LINQ-выражений и отслеживание изменений в сущностях.
  • Механизм отслеживания изменений (tracking) применяется для оптимизации операций чтения и записи.
00:44:03
Организация процесса деплоя и управления конфигурацией:
  • Автоматический процесс деплоя через CD-пайплайн.
  • Управление конфигурацией и мониторингом через Grafana и Telegram.
  • Масштабируемость и управление несколькими региональными версиями продукта.
  • Решение проблем с миграциями и обратной совместимостью схем данных.
00:30:39
Оптимизация запросов к базе данных и использование индексов:
  • Методы диагностики производительности запросов и использования индексов.
  • Создание индексов для ускорения поиска по нескольким полям.
  • Принципы выбора индексов в зависимости от сценариев использования.
00:39:11
Синхронность и асинхронность в приложениях на .NET:
  • Использование высокоуровневых механизмов синхронизации и асинхронности в .NET.
  • Ожидание завершения асинхронных операций и возврат потока в пул потоков.
  • Выбор подходящего уровня жизни зависимостей (Singleton, Transient, Scoped).
00:44:34
Архитектурные решения и взаимодействие микросервисов:
  • Создание карты взаимодействия микросервисов и способы ее автоматического обновления.
  • Реализация гарантированной доставки событий и обработки сообщений.
  • Использование Apache Kafka и RabbitMQ для обмена сообщениями между сервисами.
  • Терминология и принципы работы Apache Kafka, включая топики, партии, консьюмер-группы и смещения (offsets).
01:01:45
Вопросы по организации процессов в команде:
  • Вопросы касаются структуры команды и построения рабочих процессов.
0: Чтоб пропустить водную.
1: Так, а меня слышно было сейчас nat видно. Да, да, да, да, я, да, окей, хорошо. Так, ну значит продукт это мобильное приложение вилка куча микросервисов под corp под капотом команды есть как кроссплатформенные, так и на конкретном каком-то.
2: На каком конкретном направлении сейчас мы говорим про команду, где чистый backend это финрес, так называемые финансовые результаты клиента. Если простым языком, то это какие-то графики, статистика, аналитика, которую клиент может у себя увидеть.
3: Там в разделе анализа портфеля, где будет показано там, сколько он заработал, сколько он потерял, за какой период отчётности сейчас в целом этот раздел есть. Просто он существует там на 1 легаси решении, которое не весь функционал предоставляет, необходи
4: Бизнесу. И команда сейчас полностью переписывает с нуля. Дорабатывать это легаси не нужно, взаимодействовать с ним тоже не нужно. Оно в целом там в замороженном состоянии существует и касаться вообще не нужно будет. Оно вне Скопа этой команды по факту все бизнес, требования новые, все.
5: С нуля пишется команда, и состав у неё таков сейчас это 1 мидл разработчик, мы ищем ещё 2 сотрудников бэкэндеров, это, соответственно мидл, разработчик и senior, который впоследствии станет техлидом в команде, также там в команде сейчас есть аналитик.
6: Методолог тимлид, совмещающий с аналитикой, то есть по факту там полтора аналитика, можно сказать, и тестировщик с упором в автоматизацию.
7: По стеку технологии 8 дотнет везде мы апдейтим регулярно, до новых версий есть постгрис, ребит, кафка, монга, редис, но если говорить конкретно про эту команду, у ребят сейчас фактически только о хранилище данных и кафка.
8: Как брокер сообщений, из которого они черпают инфопотоки от различных систем. Все на микросервисах пакуется в докер, оборачивается холмом. Все это деплоится в кубер на
9: Мощностях гитлаба построен сиайсиди, там же есть кнопки деплоя на тестовую среду, деплоя, на продакшен и в целом, наверное, все из основного. Если что-то интересно, конкрет
10: Или че то забыл? Можешь спрашивать. Ответим. Да, на самом деле, пока вроде все понятно. Угу. Окей, хорошо. Тогда давай, наверно, про твой какой-то еванный опыт, с чем в последнее время приходилось сталкиваться? Над каким проектом рабо?
11: Какие проблемы решал? Ну, в общем, кратенько расскажи. Да, окей. Последнее место работы была компания, которая вела проектную разработку в сфере медицинских информационных систем. Вот конкретно мой проект был реестром электронных медицинских documento.
12: Куда стекались документы с 5 регионов России и с наших смежных сервисов. Вот всего в нашей системе было порядка, там, по моему, 15 или 16 сервисов. Вот команд было примерно столько же, может, чуть Меньш.
13: Вот оно. Наша команда состояла из 7 человек. Это 1 тимлид, 1 фронтенд разработчик, 1 системный аналитик. Остальные все бэкендеры меня изначально нанимали как человека, который будет закрывать техдолг. Вот.
14: Я его закрыл, как раз-таки перешёл в штат обычных разработчиков. Задача на самом деле довольно стандартная это поддержка сопровождения, плюс интеграция с нашими системами или сторонними сервисами.
15: Вот как-то так.
16: Окей, хорошо, понял. Слушай, подскажи, пожалуйста, вот ты упомянул, что как раз-таки изначально брали, чтобы техдолг разгребать и какое-то время приходилось им заниматься. А вот можешь рассказать, что из себя представляет техдолг на вашем проекте, это там
17: Обновление каких-то библиотек или это что-то другое? Да, да, на самом деле просто дело в том, что когда я пришёл, там, тогда наш, наш сервис, он был, получается, не b2c, он был b2b, то есть он был
18: Не для клиентов, а для наших систем, либо для других организаций. Вот из за этого очень в очень сжатые сроки приходилось выкатывать релизы. Вот из за чего плодилось очень больших, очень большое количество таких вот.
19: Штука, когда говорили, делай, сделай, как потом переделаем. Вот, чтобы можно было просто выкатывать и успевать за контрактами, которые выставляли заказчики. Угу. Понял. Хорошо, спасибо. Я
20: Понял. Тебе приходилось сталкиваться и с реббитом, и с кафкой в своей практике. Если я правильно понял, вы интегрировались через mass transit, да? Ну или мои предположения, если не верно, там не на самом деле все верно, да?
21: Storm работали через транзит? Вот с кафкой тоже. Но есть опыт работы, как с rabbit, клиент, так и с кафкой. Угу, понял. А вот тогда раз и с тем, и с тем приходилось работать. Подскажи, с чем там тебе было удобно?
22: Какие плюсы? Минусы видишь там при работе, допустим, через mass transit с этими инструментами или при работе с их, скажем так, родными нативными клиентами, которые предоставляются от там разрабов или так, ну,
23: Вообще, мне больше удобнее работать с рэббитом, наверное, просто потому, что у меня и с реббитом, а опыта больше, чем с кафкой. Вот мастран, наверное, удобен тем, что он может, ну, как бы он универсальный для большого количества очередей, типа, те, там не только rabbit, как там ещё на
24: Amazon, басы там и так далее. Вот, наверное, он как-то более высокоуровневый, чем стандартные клиенты для этой кафки. Вот, поэтому, наверное, с удобнее че
25: Нативные клиенты. Угу. Окей. Хорошо. Я вот вижу ещё, что у тебя упоминается хэнк фаер. А можешь подсказать, для каких ситуаций, для какого рода задач вы его использовали? На самом деле мы их использовали просто для джоб, там все довольно прост.
26: Угу. Ну то есть у вас были какие-то фоновые джобы? Да, да, да, да, да. Вот как раз понял. Окей, хорошо. А приходилось сталкиваться с какими-то механизмами обозреваемости. То есть, ну даже если проще, вот весь функционал.
27: Который вы делали и так далее. Он как бы оставался у вас на поддержке. Вы в дальнейшем за ним следили за его работоспособностью и прочим. Или вы его кому-то передавали? Нет, следили мы, ну, до тех пор, пока действовал контракт с заказчиком, потом уже заказ этот
28: Проект переходил к нему в руки. Угу. А подскажи, вот че из себя представляла? Ну, назовём это так, система мониторинга, типа, как вы следили за этим, там, на продакшене, на тесте и прочим. То есть вам же какие-то баги могли
29: Происходить, да. И да, да, да, у нас была команда, те, которые довольно хорошо настроили аркестрирование всех наших сервисов, потому что там их было, ну, как я уже говорил, порядка 15, 16. Вот. И все они между собой общались у нас, ну, конкретно у каждого сервиса был
30: Был свой этот механизм для похода ресурсов. Типа у нас была графана вот
31: Ну, как раз-таки, когда приходили какие секции, например, когда в логах выпадала критическая ошибка, то приходило просто в нашу теллеграм группу, сообщение о том, что выпала критическая ошибка. Вот. И все бежали смотреть, что там, что там происходит. Угу. Окей.
32: Хорошо, понял. Спасибо. Так и по куберу. Знаешь, че, немного ещё интересно, вот насколько вообще приходилось с ним сталкиваться. То есть, ну, я понимаю, что у вас было все настроено дивопсами, и давай начнём с простого. Вот как у вас.
33: Там deploy на различные среды. Это вы какие-то кнопки жали? Или вы кому-то отдавали там ссылки там на свои, не знаю, пайплайны или на свои исходники с просьбой задеплоить. У нас все было настроено через cd. У нас был контур для разработчиков, по сути.
34: Ну, просто песочница, где можно было делать че угодно. Вот. Потом был тестовый контур как раз-таки уже для тестеров, когда там прогонялись автотесты и мануальное тестирование было. Потом был, получается, препродакшн для каждого региона. Вот, и для каждого
35: Региона был продакшн. То есть сколько получается, 14 контуров было, потому что 14 из за регионов. Да, да, да. Регионов было всего 5. Вот. На самом деле, там даже было такое, что некоторые версия проекта
36: Они были уникальны для некоторых регионов. То есть в некоторых регионах были одни фичи, некоторых, другие. Прикольно, интересно. Окей. Хорошо. Смотри, давай, наверное, тогда можем потихоньку перехо.
37: Идите в сторону технической части, я, ну, аккуратно буду отталкиваться как раз от опыта, но если ты че то будешь вспоминать по ходу дела, по там интересующим тебя вопросам, можешь тоже в моменте задавать, ну или в конце останется время, то можно будет поговорить так.
38: Я тогда сейчас тыкну рекординг вам, робо, женщина скажет.
39: Что рекординг изон да, все так. Ну давай тогда начнём наверное с дутней истории. Подскажи, у вас весь ваш функционал строился на каких-то истовых апишках или это gypsy или че?
40: То, другое было. Вот интересует сам способ взаимодействия сервисов друг с другом. Ну, сервис в основном, в основе своей взаимодействии, как раз-таки по очередям, вот там, где нужно было быстро и точно дать ответ использовали. Вот слышал.
41: Просто в некоторых сервисах использовали как си контракты. Вот, но до нас такого не дошло. Угу. Окей. Хорошо, давай тогда поговорим просто про классические рестовые апишки, контроллеры, все, что вот этим с этим связано. Смотри, прежде чем запрос там попадёт в класс.
42: Контроллера твоего и метод, он там пройдёт ещё ряд этапов, которые обеспечиваются самой там платформой. Вот можешь немного своими словами рассказать, че это за этапы, что они из себя представляют и можем ли мы куда-то туда вмешиваться, какой-то свой
43: Код добавлять, подмешивать. Так, ну это называется пайплайн, обработка запроса, он же конвейер. Вот 1 из каждое звено из этого конвейера называется медве. Вот она же в можно написать свои кастомные, да, то есть можно взять какие-то промежуточные звень.
44: В этом конвейере вот, ну, добавляются они как через апп точка us. И вот. Угу. Наверное как-то так. Да, окей, хорошо, приходилось самому какие-то свои a pizza.
45: Для да, писали, получается, хендлер для ошибок, чтобы на фронтент давать ошибки в если там тробуется ошибка, то отправлять её на к этому, на фронтенд или к другой сервис в более таком, ну, щадящем, универсализированной виде и для авторизации, для
46: Токенов. Угу. Понял. Хорошо. А с механизмом?
47: Ой, вылетело из головы экшен, да, с механизмом экшен фильтров приходилось сталкиваться вот эти вот атрибуты, которые мы можем вешать на контроллеры или на методы, то есть есть стандартные там, какие-нибудь авторайз, или там http road, или там api version.
48: Есть кастомные, которые там, ты можешь сам написать и ими пользоваться. Вот с ними сталкивался когда-нибудь, а памяти вроде на самом деле нет. Ну окей, хорошо, тогда не будем их трогать. Ладно, смотри, давай про
49: Продолжим эту историю. Вот запрос к нам прилетел. Есть контроллер. Мы в контроллер, как, как, как правило, можем че то заинжектить в его конструктор, а какие уровни жизни, зависимости ты знаешь и
50: Для каких целей там какие из них существуют на твой взгляд ну их всего 3, это single, тон скоупд и треджен, вот разница как раз-таки между ними во времени ливня, синглтон, контейнеры создаются 1 раз на все приложение тренде, контейнеры это так называемый.
51: Контейнеры, то есть у них нету сохранения состояния, они создаются новые каждый раз при новой каждой новой инъекции. Вот есть scope. Это контейнеры, которые живут в рамках 1 Скопа, например, запроса. Угу. Окей, хорошо, смотри, ты упомянул?
52: Ну что, как раз скоуп существует в рамках какого-то скоупа, например, в рамках запроса. А есть ещё какие-то примеры, вот из твоей практики, когда существовал вот этот вот скоуп. Ну да, например, у нас было такое, что в рамках
53: Рассылки уведомлений в background сервисе, когда приходило время рассылки, мы создавали Скоп как раз-таки для этой самой рассылки, вот, и ну, там и жили эти Скоп, сервисы там создавали его через corp фектори.
54: Вот, и так далее. Угу. Окей, хорошо. А вот давай представим себе в ситуации. Вот ты как раз говорил с консьюмерами. Ну, пример, кстати, хороший был с этой джобой. Давай ещё 1 пример посмотрим. Вот с консьюмерами, ты говорил, в
55: Вы потребляли через брокера сообщения, ну, передавали от 1 сервиса к другому. Угу. Угу. Допустим, пускай там тот же rabbit не суть важно. Вот у вас есть консьюмер, который читает из него, и, ну, допустим, он должен сохранять вот там это событие, пускай даже без
56: Изменений в базу, да, типа, какое пришло, вот он её и сохраняет себе пузырю. Вот какой бы скоуп ты обозначил в этом примере. То есть, что им является по факту, че у нас есть, если смотреть из составляющих это подключение к
57: Это какая-то реализация консьюмера и какая-то логика сохранения в базу. Вот можешь своими словами очертить этот Скоп там где он начинается, где он заканчивается. Так ну получается у нас есть какая-то какой то консьюмер, который постоянно слуш.
58: Вот, и есть некий сервис, который, ну, не сервис, назовём его. Ну, хотя, ладно, пускай будет сервис, который сохраняет сообщения в базу. Я бы сделал так, я бы сделал так, я бы, наверное, использовал, ну, был сервис, вот у него был у него
59: Какая-то, наверное, логика и сохрани репозиторий вот репозиторий я бы сделал, наверное, синглтоном, но внутри него создание дб контекста при каждой инъекции метода, то есть через api, ой, а через контекст вектор создавал бы контекст при каждом запро.
60: Вот. И сохранил бы, наверное, было так сделал. Угу.
61: Так, внутри. Сейчас ещё раз секунду. Внутри репозитория скотт. Ну, по сути, Скоп диби контекст. Да, не внутри. Внутри репозитория есть контекст вектор, который симптонов, да, из фабрики, из фабрики. Да, да. Так. А сам репозиторий.
62: Можешь повторить, с каким уровнем? Да, сам репозиторий тоже раб. Угу. А сервис, который вызывает его, этот репозиторий, ну, на самом деле, зависит от того, какой это сервис. У нас было такое, что на некоторых проектах использовались
63: Медиатор, вот там уже сами вот эти вот хендлеры, они были бы скот. Вот. Но можно было бы и сделать. На самом деле зависит от того, что у вас конкретно в проекте происходит.
64: Угу, окей, хорошо, хорошо. Так, давай двинемся дальше. Тогда смотри, ты упоминаешь то, что приходилось с, с фреймворком работать, да? Ну да, предполагаю. Там, скорее всего. Core уже актуальный, да, да.
65: Ически, что тебе ближе? Чисто по удобству. Тебе проще эскьюэль в чистом виде запросы писать или через ормки с ним взаимодействовать? Ну, наверное, все-таки больше с орм.
66: Чтобы когда, ну, не знаю, раньше, когда я только изучал программирование, было, конечно, удобнее использовать Эскель онли. Вот. Но потом, когда руки дошли до привор, это давно, давно было. Потом понял, что можно не переключаться с контекста, когда ты
67: На 2 разных языках пишешь. Это все так удобно стало прям. Угу. Окей. Хорошо. Ну, давай про их немного поговорим вот давай представим наш стандартный пример. Надо вытащить какие-то данные по фильтру из базы. Угу. Ну че там обращаемся там. Db. Контекст, точка.
68: Users потом накручиваем условия сложно через vr да потом может быть делаем какую-то трансформацию через select и потом какую-то агрегацию там тур или лист по факту мы че сделали мы просто применили линки выражения к db сету внутри dp контекста и
69: Выходе мы получим реальные данные из базы, потому что запрос в базу вызовется и с правильным, даже сельным синтаксисом. Угу. А как фреймворк конвертирует вот этот линки, линки выражения, как он
70: Конвертирует в скьюль нативный код. Там на самом деле все довольно интересно. Есть коллекция. Вот. И при есть такой интерфейс, называется айкори, он же отвечает за запрос, вот он у себя содержит дерево выражений, оно как раз та,
71: И то есть, когда мы делаем дбс точка, например, там селект, точка, что-то ещё, точка, что-то ещё. То есть когда мы делаем эти вот выборки и условия, они все падают в это дерево выражений, а потом, когда мы i переводим кейбл, то колле материализуется и данны.
72: Это уже парситься, ну, составлять из этого запрос и исполняться уже там, провайдером зависимости от того, что мы используем. Угу. Да, окей, хорошо. А если мы говорим про историю с записью в базу, да, мы вытащили, допустим,
73: Там сущность по айдишнику, потом, ну, юзера того же, потом у этого юзера меняем какое-то из свойств, допустим, там фамилию, то есть, банально пишем там юзер точка ласт нейм равно 1, 2, 3. И потом сохраняем данные в базу через метод там db. Контекст чейндж.
74: А как earth поймёт какой скрипт надо сгенерировать на изменение, мы же ему в явном виде ничего не сообщили, все что произошло это 3 действия мы получили средствами энтити фреймворка, запись из базы.
75: Мы в ней даже не запись из базы, а по сути модельку да, да, я понял модельку какую-то в ней поменяли какое-то свойство и опять rt говорим, сохрани, как он это понял, что, ну, есть такой механизм, как её трекинг. Вот.
76: Когда достаёт что-то из таблицы или вообще откуда-либо он можно ему задать, либо c треккинг, либо c no tracking. Вот как раз-таки когда мы говорим ему c no tracking, то мы ничего не сохраняем. Вот, а когда мы
77: Говорим ему трёкать, то мы создаём ещё 1 объект, точно такой же и сравниваем, получается, все изменения с этим объектом. Вот если мы говорим про момент, когда мы ничего не трекаем, то
78: Переживаю, что изменения все-таки он пытается изменить, наверное, все поля. Вот. И как раз-таки изменятся. Те, наверное, которые, ну, реально содержат изменения.
79: Так, ща ещё раз. То есть думаешь, что если не вызывать из no tracking, точнее наоборот, если вызвать из no tracking, поменять какое-то свойство сущности и вызвать диби контекст, он все равно сохранит изменения. Просто он другим способом отследит, верно? Ну не, не.
80: Нет, я думаю, что он пытается, скажет, е, точка ком, а уже сам себя решит, если мы говорим про о, что там поменялось, не поменялось.
81: А давай вот про трекинг чуть поговорим ещё, вот как ты понимаешь себе его ценность на самом деле, ну или, или в каком виде он работает там под капотом. Это тоже связанные вещи. Ну, в плане, в каком виде? Под капотом, не совсем понял. Нет, давай.
82: Давай проще, вот в какой ситуации ты бы использовал этот метод эз, но трекинг а в какой бы не использовал? Ну, изреки, я бы использовал, наверное, тогда, когда нам нужно только читать. Тут все довольно просто, чтобы мы не создавали просто лишние прослойки, не лишние объекты. То есть это была бы небольшая оптимизации.
83: Вот там я использовал просто треки. Вот и все было бы просто в моменты, когда, когда, когда, когда бы я использовал Трёкин, ну, наверное, тогда как раз когда я работаю с сущностью, изменяю её постоянно, вот тогда бы я использовал трекер.
84: Вот, наверное, так. Ну да, логично все в целом. Так, а вот исходя как раз из этих формулировок, ты абсолютно правильно их описал. Как думаешь, ещё раз, тогда че произойдёт, если мы вытащим юзера какого-нибудь, да?
85: Через as no tracking поменяем в нём че то и попытаемся сохранить средствами диби контекста в базу. Он что-то будет с этим делать или нет? Нет он это будет делать. Он скорее всего составит запрос на изменения. Вот просто
86: Я подозреваю, что скинет он туда не только изменённое поле, а попытается скинуть все поля, которые есть у слушай, ну на самом деле нет, он, он как раз вот ты правильно все писал, вот этот change, трекер механизм пойдёт сравнивать с тем, что у него
87: Скажем так, внутри было сохранено оригинальные объекты с вот там твоими изменёнными. Он увидит, что он эту сущность не трёкал. Ну и сравнивать, значит её не надо и он не вызовет никакой запрос на базе в этом случае и
88: Так и должно быть. То есть это и задумано, что вот это tracking ты правильно описал, что он для оптимизации используется, типа он там чуть меньше места жрёт, чуть быстрее работает и для операции чтения как раз-таки для этого и был сделан и как раз в такой парадигме
89: Раз он для операции чтения, то вся нижележащая механика строится на том, что ну раз я ничё не трёкал, то мне ничего проверять и не надо и сохранять, значит ничего тоже не надо. Интересно, мне почему-то казалось, что я когда-то пытался сохранить объект, не трек.
90: Вот, ну да, там да, ты прав, ты 1 нюанс тут наверное упустил что можно так сделать, если в явном виде использовать методы фреймворка, вот эти вот там add update или эти да, да, все, я понял, да. Ну я вот как раз про них имел в вид.
91: Вот, да, вот если в явном виде их прописать, как раз вот описаны такой подход с тем, что он, типа, там обновит все, да, да, тогда просто он будет, да, все, я поняла. Угу. Да, окей, хорошо. Слушай, а подскажи, а как у вас была организована работа с миграциями?
92: Проектах. Ну, я подозреваю, что у вас код ферст, наверное, какой-то был. На самом деле, тут все довольно интересно. Я поработал в успел поработать в 2 проектах. Вот на нашем проекте использовался, да, действительно, код ферст Миграция, там все довольно просто было, а на смежно
93: Проекте соседнем, там использовался лики Бейс, чтобы отвязать миграции от самого проекта самой рм. Угу. Интересно. А тогда вот в этих 2 проектах подход к накатке мигра.
94: На там тестовый или production среды отличался или был идентично реализован? На самом деле? Нет, почти не отличался. А можешь рассказать, вот как он у вас был реализован? Да, там довольно все просто. Это получается, когда начинался аплай с сборки приложения, он снача
95: Запускал скрипт миграции, который был в папочке со скриптами. Вот если Миграция вставала успешно, без ошибок, то он запускал приложение, если же были какие-то ошибки, то бил, парился и как раз-таки прислал, прислал уведомление о том, что у нас все лежит. Ребята, сделайте с ним, что
96: Вот, и там, и там, там, где был ликвид Бейс, запускался стандартный ликвибейсе мигратор, там все просто. А где там был специальный проект мигратор. Вот запускался же он. Угу. Понял. Смотри, давай как раз.
97: Можем этот подход дальше обсуждать, учитывая, что у вас там тоже че то все в кубере, кажется, было, да, на этих проектах. Ну да, да, подозреваю, что у вас там все экземпляры сервисов.
98: Там поды крутились не в единичном экземпляре, да, а во множественном числе там, для какого-то масштабирования нагрузки. Ну хотя бы в 2 наверняка у вас были развёрнуты. Вот представим ситуацию, что есть у тебя сервис, у которого прошлая версия. Ну, назовём её
99: Текущий, стабильный, развёрнуто там на продакшене и там в нескольких экземплярах, пускай в 5 копиях. И ты запуска, ты по задаче, тебе требовалось поменять схему данных. Давай для простоты считать, что переименовать ко
100: Там name на first name, ты сделал задачу, ты там протестировал все локально написал миграцию. По факту Миграция, ну, примитивнейшая, да, там типа alter table ренейм колон, типа ты переименовываешь колонку, все будет работать, ты за
101: Запускаешь вот этот ваш пайплайн, там сборки диплоя. И как раз, как ты описал, там 1 из первых Шагов предварительных будет в том, чтобы накатить эту миграцию на среду, он, он её накатит и даже без ошибок, потому что Миграция технически правильно написана и к базе применится, и да.
102: Уже уложится в какой-то тайм аут выполнения. Дальше переходит к этапу деплоя. Ну вот смотри, даже до момента этапа деплоя остаётся окно в несколько, там от нескольких секунд, может быть до нескольких минут, когда
103: У тебя на бою все ещё крутится старая версия сервиса версии сервиса старой. Да, я понял, понял. И ты уже поменял схему базы данных, а старая версия ничего не знает про новое название колонки и, соответственно, там все запросы клиентов. Ну или там запросы.
104: Консьюмеров твоих. Короче, все взаимодействие с базой будет падать с ошибкой, типа, где я ничего не знаю про колонку, которую ты хочешь. Типа, че за user name? Я ничё такого не знаю. Вот сталкивался ли с такой проблемой или если не сталкивался, можешь поразмышлять, как бы решал её, так.
105: Ну, насколько я помню, у нас была реализована такая тема, что получается, когда вот у нас, допустим, запущено 2 приложения, 2 приложения, когда мы хотим начать деплоить новый, новую версию проекта, у нас
106: Было так, у нас была вот у нас было 2, если у нас было 2 Пода, то у нас было 2 версии, ну, 2 базы данных, то есть мастер и реплика для чтения, вот как раз-таки для того, чтобы, ну, когда поднималась новая версия, получается, поднималась ещё
107: Реплика мастер, мастер базы данных. Вот и тот, кто писал в мастер, типа он писать переставал и типа они все, короче, читали только реплику. Вот тогда на мастер накатывал.
108: Миграция и поднимался новый этот, как он новый под поднимался. Вот как раз-таки, если под поднялся, окей, все нормально, то получается он становится мастером старый, старые поды, они
109: Ну, они либо не убивались, либо продолжали работать, либо лично как раз-таки убился. Вот и не нужны они убиваются. Вот было то так. Слушай, а я вот немного упустил. Получается, при каждой новой раскатке у вас создавались?
110: Новые реплики, базы вот этими же скриптами. Да, да, да.
111: Так, новые реплики базы, а соответственно, миграции у вас применялись к мастеру, да, на мастера потом просто актуализировались. Во, смотри, даже в этом примере получается у тебя
112: В любом случае, накатка миграции и deploy сервиса, это 2 разных шага. Ну, они с какой-то близостью выполнятся, конечно, там в пару миллисекунд или пару секунд, но все равно действие не атомарное. Да, у тебя же сначала Миграция. Да, да, да, я поняла. Вот.
113: Вот даже в этом примере Миграция накатывается на мастер и те существующие реплики, получается уже, ну, если к ним Миграция была не применена, то они там не смогут получать данные из, ну,
114: Ооо колонки, но если у вас как-то там было настроено авто реплицирование вместе со схемой, то окей, допустим, к ним эти колонки пролетят, но в целом старая версия сервиса все ещё остаётся висеть и ничего про старую колонку уже не сможет получить в вменяемом виде, потому что да, да, я вот это, я понял. Та
115: У нас довольно все хитро было. Доп. Делали, так, что когда-таки поднимается Миграция, вот поднимается вместе ещё и 1, 1 под над новой версией. Вот тогда, получается, был блок нагрузки, который перекидывал все запросы со старых реплик.
116: На новую. Вот. Потом она уже сама по себе масштабировалась и под себя создавала новые реплики. Если нужно было, если не нужно было, то просто переключалась на старую. Интересно, нетривиальное решение. Кажется, как-то дорого, сложно. Ну то есть оно будет работать.
117: А не подскажешь? Ну, если знаешь, почему ребята решили именно так делать. То есть хороший вопрос. На самом деле, я им когда не задался, н, мне просто сказали, что там и все очень сложно, то лучше не лезть. Окей, ладно, давай тогда. Ну, в целом такая схема, конечно.
118: Работало. А давай исходить тогда из другой вводной, что все, что у тебя есть в распоряжении, это твои исходники сервиса и все, что с ними связано, да, в том числе Миграция, это вот этот вот там твой пайплайн или твоя кнопка диплоя прод.
119: И ну и все, и типа ты не можешь сам реализовать вот эту вот механику с поднятием реплик и переключением этого трафика. То есть все, что ты можешь делать, это менять свои исходники, деплоить в прод и
120: Там следить за здоровьем этого, на продакшене, при этом по факту, пускай там будет только мастер без реплик в продакшене. Да, я понял. Ну, если бы я делал так, то, наверное, я бы не менял имя на
121: Колонке, я бы создал новую колонку рядом с новым именем. Вот. А получается, когда бы я сделал миграцию, там, получается, старые реплики, ну, старые версии приложения, они бы, мы бы их либо убили, либо подняли новые. Вот. И потом уже скриптом перекинул данные, из которые перезаписатьс.
122: Салли, новую колонку. Окей. Хороший подход. Да, супер. Здорово. На практике не приходилось с таким сталкиваться. На самом деле, вроде нет. Вот, может, может, был, но я не помню уже. Угу. Ну, паттерн отличный.
123: У нас в целом все ему стараются следовать при там, каких-то несовместимых изменений, просто чтобы они, ну, просто, чтобы все было обратно совместимы, да, на уровне всех видов pr. Да, хорошо. Слушай, а подскажи ещё, ты упоминал то, что
124: Тоже приходилось по началу сталкиваться вот с вопросами оптимизации запросов к базе и взаимодействия вообще с базой приходилось сталкиваться, да, было дело. Можешь рассказать в целом. Ну давай вот представим, падает задачка, типа какой-то у вас она та.
125: Метод начинает долго работать. И давай начнём с того, что ты ещё даже не знаешь, что это долго. База работает, может она долго не работает по факту. Че у тебя есть. У тебя есть какой-то метод контроллера, да, который долго начал отвечать в нём?
126: Есть какая-то бизнес логика, есть какая-то там инфраструктурная логика и конечно же там обращение к базе данных. Вот можешь свой паттерн мышления, разбор этой истории предложить, как бы ты исследовал так, да.
127: Понял, понял. Так. Ну, для начала я бы, наверное, попросил, не попросил. А я бы сам попытался затестировать всю эту тему. То есть то, как это работает, например, на тестовом контуре попытался бы дёрнуть метод, вот смотреть.
128: Вообще как он там выполняется по шагам потом а если можно как-то поправить бизнес логику так чтобы все было оптимизировано, не лезть в базе, то все супер. Собственно смотрим на код. Если есть где то какие-то неоптимизированные долгие места, то правим если нет, то ну тут уже надо
129: Смотреть. Возможно дело действительно в базе, поэтому как бы смотрим какие у нас вообще, сколько у нас вообще есть обращений к базе. Вот если чисто по приколу кто-то сделал вместо 1 запроса 12000, то ну тут
130: Надо все это либо в 1 запрос скомкать, либо как-то наоптимизировать. Вот получается есть у нас какой-то запрос. Далее смотрим как он у нас выполняется. Вот можно использовать айс эксплор алайс.
131: Смотреть, как у нас таблицы мержится. Вот если есть какие-то таблицы, которые очень часто используются вместе, то есть часто джонится друг с другом, можно перейти к денормализации. Вот это все для чтения. Если же у нас проблемы на за
132: То есть, если мы, например, упёрлись в пропускную способность не прогресса и не можем уже физически больше писать, то можно использовать, наверное, шардирование для того, чтобы можно было эффективнее писать. Вот я как-то так думаю. Угу. Угу. Слушай.
133: Да, ты, кстати, верно, упомянул команду при там эксплейн, эксплейн алайз. А можешь простыми словами сказать, вот вот ты её вызвал, и тебе выдался план запроса. А вот на что в нём ты бы
134: Обращал внимание, чтобы понять, типа, да, все окей. Меня это устраивает или нет? Не окей, надо там че то поколдовать там над индексами и их составляющими. Ну, там, на самом деле, все довольно просто. Там, получается, вылезает дерево, табло, прям ручка.
135: Берет и говорит, что он делает. То есть каким он обращается, какие типы джоинов он использует. То есть там дон по хэшу, по селективной, там, рекурсивной и так далее. Вот там смотреть. Уже конкретная ситуация, наверное, зависит, если у нас
136: Какие-то, какие-то индексы вот можно индексы попробовать навесить может поможет ситуация вот.
137: Да, окей, хорошо. А вот смотри, ты как раз упомянул индексы, приходилось сталкиваться с основными индексами. Ну да. Ну, короче, композитный, которые, да, да, да, да. Который вместе с этим хранит ещё какие-то данные. Да, понял, да.
138: Вот давай представим себе ситуацию, что там у нас есть табличка паспортов. Там есть 2 колонки, серия и номер паспорта, видео и задачи с реальных собеседований на сайте хак собесов точка ру. Они пока что не индексируются. Хватит гадать, что вас ждёт на интервью. Переходите и получите. Пре.
139: Преимущество перед другими кандидатами прямо сейчас. Нам, соответственно, надо ускорить этот поиск, добавить какие-то индексы, вводные тебе дают следующее, что люди ищут во всех 3 форматах, они ищут и только по серии, и
140: Только по номеру.
141: И по обоим колонкам, и по серии, и по номеру. Угу. Вот какой индекс или индекс может быть несколько? Ты бы навесила в данной ситуации на эту табличку? Так, ну если мы говорим только про серию, то насколько я
142: Могу судить, насколько мне известно, там, насколько помню, у каждого региона в паспорте паспорт делает свою серию. То есть там есть какие-то заранее ограниченные ренжи серии паспорта для конкретных регионов, то я бы навесил индекс на серию, если мы делаем выгрузку по региону, например, вот
143: Или если мы делаем конкретно выгрузку по серии номеру, то она весила бы индекс одновременно и на серию, и на номер. Вот. Ну если мы ищем по номеру, то, очевидно, индекс на номер. Так хорошо. И вот давай теперь вернёмся к требованиям, то есть требования
144: Будут искать по всем 3 вариациям. То есть это типа, а одновременно, то есть, ну как тебе надо быть готовой к ситуации? Тебе надо быть готовым к ситуации, когда все 3 варианта поиска валидны и будут искать.
145: 3 способами. Соответственно. Вот следуя из этого, ты перечислил как раз разные подходы для 3 разных вариантов. И вот финализируй какой 1, или все эти индексы, или там часть из них ты бы вот как раз навесил для этой истории. Так
146: Ну, можно, да, тогда составить, наверное, сделать в составной индекс на серию, который будет связать себе ещё и номер как раз-таки для той ситуации, когда мы ищем по серии вот отдельный индекс на серию номер, это когда мы конкретно хотим найти.
147: По конкретной серии номер. Вот. Ну и, наверное, отдельно на номер. Ну, можно и то записать, конечно, я просто не уверен. А нужно ли это? То есть, опять же, зависит конкретных задач. Угу. Окей. То есть сводим.
148: Это к тому, что создал бы 3 индекса как раз-таки на все эти 3 ситуации, да? Ну да, да, по 1. Окей. А если рассматривать вот этот составной индекс, который ты как раз-таки предложил навесить на 2 колонки, на серию и номер. Угу.
149: Понятное дело, он однозначно бы работал, если мы искали по 2 колонкам. А если бы мы искали только вот только по серии? То есть у тебя есть составной индекс, который как раз-таки говорит, типа покрывает серию и номер, но ты ищешь только по серии, вот он.
150: Бы использовался этим индексом или нет. Ну, насколько мне известно, насколько я могу рассуждать, то мне кажется, да.
151: Ну, то, что по там, потому что под капотом очень сильно оптимизирован. Вот скорее всего, для таких кейсов тоже есть оптимизация, а потому что даже есть такое требование, что если мы хотим использовать основные индексы, то лучше для поиска по ним.
152: Использовать операторы этого не больше, меньше, а как от этого чёткого равно вот, потому что иначе становится очень оптимизированным. Угу. Так, хорошо. Тогда, учитывая эти вводные, если вернёмся к оригинальному запросу,
153: К оригинальному вопросу ты сказал как раз, что ты бы навесил 3 индекса. А вот в условиях, если составной индекс все-таки работает не только по обоим полям, но может работать там ещё, допустим, по 1, то как бы можно было изменить
154: Предложенный подход, да, опять же, на самом деле зависит от конкретных задач, потому что если мы используем задача, если че есть конкретно, вот задача, типа, а то, да, искать по всем 3. В этом и есть задача, да? Ну тогда че
155: Наверное, искать по, ну, вешать индекс просто на серию номер. Вот тут я просто отталкивался от того, что когда мы, хотя, да, наверное, такого не может быть, наверное, да, лучше серию номер просто повесить и все.
156: То есть только 1 индекс оставить? Ну, можно, да, можно оставить только ИНН индекс. Окей. А если вот в этой ситуации мы оставили 1 индекс и будем искать по номеру, соответственно, он будет применяться.
157: Нет, да, ловкое замечание, да, он тогда, если мы будем искать только по номеру, то он, он не будет применяться, потому что мы исключили серию, тогда лучше навесить на серию номер и номер.
158: Да, это лучший вариант, действительно, потому что составные индексы покрывают сразу несколько полей, и они могут точечно искать по полям те, что идут в левой части индекса. Если да, да, да, окей. Хорошо. Так.
159: Давай двинемся тогда дальше в сторону. А, нет, чуть чуть назад на самом деле откатимся. Че то я забыл, извини, про дотнету, историю нашу. Угу. Можешь своими словами описать то, как работает наша там высокоуровневая синхронность. То есть у нас есть
160: Тип таски и не только её. У нас есть там ещё ключевые слова синовейт. Все это нас избавляет от ручной возни с потоками, но как все это работает под капотом, можешь своими словами. Так, ну если говорить про конкретно синквей, то это просто
161: Сахар, вот там пока потом все разворачивается в машинном состоянии с состояниями до вайтов, между вейтам, после вайтов. Так, прошу прощения. Вот когда мы создаём новую Таску, получается у нас есть планировщик задач, которые раскидывают эти задачи по тредам. Вот у нас получается
162: Трек это очередь из несколько идущих подряд тасок.
163: Так, да, хорошо. Смотри, давай представим пример, что у нас есть как раз обращение к базе, допустим, через тот же фреймворк, да, мы ветим какой-то вызов. Угу. Запрос, запрос улетел там по сети 100.
164: База, мы ждём его ответа. Он же там долго может возвращаться. Секунды, минуты, а иногда даже часы. Вот что будет с потоком, который обрабатывал этот запрос. Он будет ожидать ответа на протяжении этого времени? Или он че то ещё?
165: Ну, если есть, нет. В общем, если это исполняющий поток, то мы, получается, говорим задачи о том, что вот смотри, у нас вот есть задача, ну-ка, давай разберись с этим. Он берет эту задачу, берет 1 попавшийся поток с пулл потоков, вот, и говорит, типа
166: Занимаешься вот как то так-то есть, когда, ну очевидно, что если как если у нас в операции, то какой-то поток в любом случае будет сидеть и ждать, пока эта штука, она до это довыполняет.
167: Так, слушай, извини, у меня немного залагало, я 1 часть услышал про пулл потоков и так далее. А вот про 2 как раз именно когда будет выполняться, не услышал. То есть вот мы ждём эвейт, ждём, когда выполнится. Че произойдёт с потоком, который запустил этот await? Ну зависит.
168: Ну, наверное, он просто будет заниматься чем-то своим, чем-то, ну, чем-то своим, в общем, будет заниматься до тех пор, пока у таски не появится состояние.
169: Ну, ну, в целом, да, но как бы, переформулировать бы это. То есть, вот когда ты говоришь, когда ты говоришь, что он будет заниматься чем-то своим, этот поток, да, а чем, вот как ему понять, что ему надо? Чем?
170: То заниматься, он же там не сам понимает это, ну там для этого есть тоже свой thread менеджер, вот, который всем этим занимается, который говорит, кому что делать. Конкретный момент времени. Угу. Ну, ну, в целом, да, короче.
171: Чуть проще сказать, то после того, как авет вот такой сетевой запустится, поток просто вернётся в пул потоков, как незанятый, и будет ждать действительно, когда тред менеджер ему. Да, да, возьми такую-то задачу или сякую. А вот
172: Как результат этого эвейта, да, там 10 секунд спустя нам пришёл ответ, а какой поток продолжит обрабатывать дальнейший код? То, что начал или какой-то другой зависит от того, как мы ветили, если мы использовали конфигуру Вейт,
173: То он вернётся к тому, который запускал синхронную операцию. Если же мы говорим, что мы не будем ожидать, то он берет тоже случайный поток из пулу потоков и говорит ему теперь этим занимаемся. Угу. Окей, ладно.
174: Ну хорошо, да, все так, слушай, можешь немного ещё рассказать про вот у нас есть чудесные линки с кучей методов расширения на все виды коллекции там и так далее, да, но все это зиждется на 1.
175: Базовом интерфейсе номер был. И не сказать, что он богат на функционал, у него там всего лишь, ну короче, очень, очень мало там свойств или методов там get нумератор и все, больше ничего нет. А вот
176: Можешь своими словами рассказать, в чем ценность именно такого вида интерфейса аумерл, на твой взгляд? Типа, почему, например, мы из него не можем там размер коллекции получить или не можем там по индексу обратиться к методу, ничего этого в нём.
177: Нет, это там другие наследники этого интерфейса или конкретный тип реализуют, а там только этот нумератор возвращает и больше там ничего делать не умеет. Вот зачем он нам такой? Ну потому что, по сути, это и не коллекция никакая. Это просто контракт, который соблюдают коллекции.
178: Вот, то есть он в себе, по сути, ничего не содержит. И не только тогда, когда мы его приводим к коллекции. То есть, когда мы его материализуем, говорим, типа турист или трейсинг. Угу. Ну, пупум.
179: Это просто механизм для универсальной работы с любыми перечислениями. Окей, да, хорошо. Это более красивое определение. Понятно. Да, хорошо. Так, та, та, та, та, та. Слушай, давай, наверное, пару архитектур.
180: Задачек разберём, Ларион, прежде чем там к архитектуре перейдём. Ты че-нибудь по теоретической части хочешь обсудить ещё? Да? Нет? Угу. Да, хорошо, давай дальше. Там вне контекста технологии, просто на мышление. Вот как ты себе такие
181: Представляешь, вот смотри, возможно, вы даже сталкивались с такой проблемой у себя на проектах. Вот представь, там у вас много там сервисов, микросервисов, систем, короче, много различных систем, развёрнутых там, где-то на продакшене и
182: Уже их не десятки там, а сотни. И вам бы хотелось составить какую-то примерную карту ваших сервисов, чтобы понимать, кто с чем взаимодействует. Понятное дело, руками можно попытаться собрать. Это 1 вариант очевидный, но он не прокатит. Типа сложно.
183: Плюс актуализировать потом неудобно. Все это хотелось бы че то более менее автоматизированное, даже если не идеальное, но хотя бы примерно работающее, понятное дело, там фронт, разрабы все это отрисуют. Нам нужно только собрать эти данные. Ключевое, что нам нужно собрать.
184: Значит, сервисы, которые взаимодействуют друг с другом и способ их взаимодействия. Давай как раз на вашем примере, пускай это там, либо по пускай реббит или kafka на твоё усмотрение. И 2 вариант взаимо.
185: Действия, там это рисовая фишка и вот нам бы как-то собрать вот эти данные со всех этих систем. При этом там у тебя есть полный карт бланш, ты можешь либо написать полностью своё решение, если хочешь, которое само все будет собирать.
186: Образом. Либо если тебе известны какие-то там внешние, коробочные, можешь предложить их, либо можешь предложить просто какой-то подход и навязать его всем командам, типа, ребята, делайте все вот так вот. И тогда наша карта микросервисов там будет в актуальном состоянии. Вот можешь
187: Размышлять в таких вводных, в какую бы сторону ты двигался и че бы предлагал своей команде. Угу, угу. Понял. Так. Ну, ну, ну, наверное, я бы начал с того, что нам получается нужен какой-то 1 сервис для того, чтобы
188: Как раз-таки собирать эту информацию о сервисах, чтобы он знал о том, кто, где живёт. Вот. Угу. Вот. А потом он должен как-то знать о том, кто где находится. Вот, поэтому was
189: У него было бы какое-то подобие рестапи, которое принимало бы в себя информацию о сервисе, например, его ip адрес, о том, что это за тип сервиса, там это rest не rest вот может это какой-то брокер сообщений, вот и так далее и
190: И по возможности, он бы, наверное, каждые там, минуту, секунд, 30 или каждые 30 секунд он бы эти сервисы мог чекать. То есть у нас получается, если бы мы, мы знали, что это какой-то готовый заранее тип. То есть, например, если это апп, то можно было бы договориться со всеми командами о том,
191: Что у нас есть то, что все апи должны соблюдать некий контракт в виде того, что у него должен быть эндпоинт для того чтобы можно было чекнуть вот тоже самое касается и давай тогда da хороший понт давай тогда наверное хелсчеки опусти.
192: Но нас, оно нас не будет интересовать. Типа, жив этот сервис или мёртв, да, хорошее направление выбрал. Давай исходить, что там у всех все отлично и так далее. И нам просто нужно собрать картину взаимодействия этих систем, да, на самом деле это все довольно просто. Это прост.
193: Сделать сервис, который принимал бы в себя, ну, у него был бы растапи, вот, в post методе, например, он принимал в себя там, ну, как раз-таки, что за сервис, например, условно его
194: Идентификатор тоже самый ip адрес или что-то другое там на самом деле не принципиально вот потом что за тип сервиса то есть это апп, это gc апи и так далее вот если например это брокер сообщений, то можно дать ему такие поля в виде кого с чем он соединяет. Вот.
195: И потом просто, наверное, каким-нибудь get методом выдавать как раз-таки всю эту информацию. По сути, это просто будет некий набор, ну, координат. То есть это будет граф, вот можно даже какую-то графу завести условно.
196: Смотри, интересный подход. Ну давай представим, вот как раз ты сказал, вот будет какой-то endpoint, ручка, куда другие сервисы должны сообщать о себе, да, типа с краткой информацией о них. Окей, ты таким образом будешь собирать информацию о
197: Твующих сервисов, но я пока не очень понял, а как в этой схеме мы соберём, вот как раз ты правильно упомянул, типа граф, да, как мы будем собирать вот эти ребра, типа какой сервис, к какому обращаются по там ристу или по реббит, вот как эта инфа туда будет
198: Это будет там же, в том же эндпоинте лежать или что-то другое. Ну на самом деле, да, он может просто, но сказать о том, что куда он пишет. То есть каждый знает, куда он пишет. Можно, например, сделать какую-то универсальную структуру для транспортной инфраструктуры.
199: В переменных окружения. То есть, например, какой-то универсальный, не универсальный какой-то стандарт по тому, как мы собираем, например, connection стринги, чтобы можно было знать куда ты пишешь. Вот, ну как раз-таки он бы туда пропинговал о том, кто куда пише.
200: What? Понял. Ну, в целом можно, получается, сформулировать так, да, ты предлагаешь сделать некий сервис, агрегатор этой информации, да, куда хак собесов, точка ком, эйчар полюбит вас, конечно.
201: Сервисы в явном виде сами пушили бы инфу о себе и своих взаимодействия, да, там можно не часто, можно условно, раз в 10 минут, 20 минут. То есть там не прям принципиально. Даже если у нас будет много сервисов, то, ну, нагрузка, условно, 1, 2 запроса в минуту, это, ну, ничего страшного.
202: Угу. Окей. Ну, в целом неплохое решение работало бы. То есть мы сделали как бы механизм у себя и предлагаем остальным. Пользуйтесь этим механизмом, если хотите, чтобы вы появились на карте.
203: Окей, окей. Так, давай ещё 1 примерчик тоже про вот это взаимодействие, допустим, есть у тебя сервис, а, который регистрирует пользователей, там у себя в базенке есть сервис б, который
204: Даже не б, а там, б, ц, д е и так далее, которые потребляют через брокер сообщений события о том, что пользователь зарегистрирован. То есть твой сервис не просто сохранил базу, а записал ещё в этот брокер сообщений событие о том, что юзер
205: Создан и кто угодно может подписаться на это сообщение и делать че угодно. С этим ты владелец сервиса, который регистрирует пользователей. И у тебя стоит требование о гарантированной отправке события в вот эту шину данных. Любой
206: Ценой. При этом мы понимаем, что возможна же ситуация, что ты базу сохранил, а брокер лежит. Конечно, девопсы там его поднимут через минуту, час или когда угодно, но это произойдёт не сразу, а сообщения тебе терять нельзя. Нужно
207: Чтобы оно гарантированно улетало. Вот как бы такую проблему решал. Да, тут на самом деле все довольно просто. Я бы, наверное, использовал паттерн ноут бокс. Это когда мы в рамках 1 транзакции записываем в, ну, в таблицу с юзерами нового юзера и в таблицу с
208: Таблица о том, что мы нового юзера создали вот это делается в рамках 1 транзакции а так как нам по гарантирует атомарность, то мы либо создадим нового юзера и нового юзера и запись таблицу, либо ничего не создадим. Вот и был бы какой-то бэкграунд сервис, который бы
209: Из этой таблицы че то вычитывал. И когда появляется новая информация об новом пользователе в таблице аут бокс, то он бы просто пушил информацию в брокер и, ну там все уже понятно было. Угу. Окей, хорошо.
210: Приходилось самому реализовывать бокс да да, было дело.
211: Пу пу пу. А давай с другой стороны рассмотрим эту историю с принимающей. Типа ты теперь читаешь сообщение. Очевидно, это какой-то консьюмер вычитывающий, да, и мы полагаемся на какой-то контракт. То есть мы вычитываем там вот это Байтер из шины, стерилизуем его.
212: Нашу модельку, но мы же можем столкнуться с ошибкой детализации не по нашей вине. Может кто-то кривое сообщение там положил, да и вместо джейсона, а может быть на самом деле по нашей вине. Может мы че то забагованное залили и
213: Нам нужно соблюсти следующее требование. Нужно не останавливаться в обработке сообщений из очереди. Нужно продолжать все новое и новое отрабатывать, не зацикливаясь на этом битом. Назовём его так, ну и при этом терять это битое сообщение тоже не хочется, потому что
214: Там завтра ты проснёшься, увидишь Алерт, и надо будет разобраться, это баг на нашей стороне или на другой команде, и на кого заводить баг. Вот как бы такую проблему решал, чтобы соблюсти оба условия. Так, ну на самом деле все довольно просто.
215: Мы говорим про условно Ревин кью, то мы просто от сообщения отказываемся, когда, если мы по, мы просто говорим, что мы это сообщение не принимаем, а следовательно, оно уходит в пул мёртвых сообщений, то есть и оттуда уже есть какой-то сервис.
216: Который эти байты учитывает и как бы просто ругается о том, что, ну вот, вот такое сообщение, типа, на, с ним делать. Угу. Окей, хороший подход. А вот этот, ну, paul, сообщение, которое упадёт в пул мёртвых.
217: Сообщение, оно автоматом реббитом туда перекладывается. То есть это, скажем так, фича из коробки. И ничего для этого делать не надо. Или нужно че то там донастроить. Это из коробки есть. Ну, называется такая x Леттер д кью. Вот это очень много сообщений, то есть
218: Из коробки, если че, не смог никуда спригнуть сообщение, обработать его, то он просто говорит, типа, ребята, вот теперь это, это туда, типа, смотрите, что хотите. Угу. Хорошо. А приходилось сталкиваться с этим, настраивать вот эту механику на стороне работа.
219: Ну, вроде, да, вроде было. Угу. Окей, пу, пу, пу, пу, пум. Так, давай, наверное, я че то вот забыл ещё 1 секцию про кавку мы с тобой не поговорили, ты вроде.
220: Сталкивался и с кафкой с. Угу. Вот смотри, можешь кратенько описать и то, и другое. Чем они похожи, чем они отличаются? Какие плюсы? Видишь, в 1, какие в другой. Так, ну, тут все довольно просто, на самом деле, и то, и то.
221: Это брокер общения данных нужна для синхронной работы микросервисов. Вот. Но кафку можно использовать ещё и как хранилище, потому что кафка в плане сохранения данных очень надёжная. Вот это кстати, но рэббит, он намного быстрее, чем кафка, у него куда выше пропускная способность.
222: Их концептуальное различие в том, что rabbit это умный отправитель, но глупый получатель. У кафки же это, наоборот, глупый отправитель, но умный получатель. То есть если мы говорим конкретно про rabbit её, то есть мы можем прям
223: Настроить куда, что, как и как мы, как и когда мы хотим отправить, а кафка же наоборот, мы просто скидываем сообщение в топик. Вот. И там пускай сами разбираются. А на стороне потребителя же мы можем настроить там кучу крутых штук у насдаже, насколько помню, специально.
224: Подобные механизмы для работы с топиками. Вот. То есть тут прям вот так вот, наверное, вот, ну и, как я уже говорил, кафка, она такая очень, как сказать, ну, консистентная, то есть она данные почти не теряет. Вот, то есть, если что-то в кафку, поп.
225: То оно там останется до тех пор, пока не привидится, что-то прям невероятно невероятное. Угу. Вот смотри, ты упомянул интересный термин в кафке топики. Ну, это аналог очередей, да? Угу. А внутри, ну,
226: Представьте, к тебе в команду пришёл новый человек, который с кафкой не работал, не знает, че она из себя представляет все, что знает. Ну, какое-то там брокерское общение и все. А сможешь какую-то базовую терминологию кафки объяснить для этого человека, чтобы он в общих чертах представлял, что
227: Что да, ну на самом деле, да, то есть есть консьюмер продюсер, он же потребитель, отправитель. Вот есть все сообщения, которые мы скидываем в кафку, мы скидываем их в топики, вот топики могут делиться на партийцы партий.
228: Можно масштабировать сколько угодно. Вот там, насколько помню, по крайней мере, мы с такими ограничениями не сталкивались. Вот. Ну а в чем ценность? А в чем ценность? Партийцы, вот ты говоришь, да, топики могут быть разбиты на партийцы. А зачем?
229: Они нужны вообще, эти разбивки. Так, ну мы получается 1 топик, 1. 1 очередь делим на несколько под очередей, куда сообщения сортируются. То есть мы доставляем, мы гарантируем равномерную доставку сообщений, разделение сообщений на несколько потребителе.
230: Вот, или же если мы хотим, например, масштабировать количество партийцев, то есть увеличить пропускную способность тупика.
231: Угу. Вот давай представим себе как раз 2 ситуации. Значит, ситуация 1. У нас есть топик из 5 партиций, и кто-то в него туда пишет, нет у нас
232: Есть наш сервис аналитики какой-то там, он там пускай крутится в 1 экземпляре, вычитывает эти сообщения и все с ним окей, появляется, ну даже не появляется. А нам надо написать другой сервис.
233: Который будет для других целей вычитывать сообщения, например, отправлять уведомления. И вот если мы просто сейчас задеплоим этот новый сервис и подключим к тому же топику на вычитывание, он будет конфликтовать.
234: Одни и те же сообщения с нашим предыдущим сервисом, который аналитикой занимался, или они будут, скажем так, независимо друг от друга потреблять все эти сообщения и не будут мешать друг другу. Так вот, я насколько на самом деле
235: Не помню, это делается ручками или нет. Вот то что если там какая то какие-то механизмы, мне кажется то что можно настроить топик так чтобы он, когда появился новый контенер, автоматически поднимал новую партийца.
236: Угу. Окей, хорошо. А что-нибудь про термин консьюмер группы, знаешь, сможешь описать, что он из себя представляет? Ну, это как раз-таки такая группа, которая, ну, группа потребителей, которая стоит, над каким?
237: На топиком, вот, которые говорят о том, что там, короче, между ними есть какое-то делегирование, вот делегирование партийцев, насколько помню там, либо сейчас скажу.
238: То есть если у нас количество партийцев меньше, чем количество консюмеров в kontier группе, то не все континер будут иметь данные, иметь, иметь к партийца, то есть они будут просто ждать, пока они либо добавится новый партиец, либо
239: Будет ждать. Угу. Смотри, а вот в том примере, который я говорил, когда мы 2 сервиса подключаем к этому, к 1 и тому же топику, вот ты бы их определял в 1 консьюмер группу или в 2 раз?
240: Ну, наверное, в 1.
241: Угу. Окей, хорошо. А с термином офсет сталкивался ещё с точки зрения кафки, понимаешь, че он значит, это то, блин. Так, если не соврать, не сильно помню гавки, но, по моему, эт.
242: Что-то про то, как шаг между учитан сообщений. То есть мы можем вычитать, например, каждое отчётное или каждое нечётное сообщение. Да, да. Ну не, не совсем там не каждый чётный, нечётный. Ну да, да, там, да, мы сами построим. Ну вообще.
243: Сет это, скажем так, то, на каком сообщении твой консьюмер сейчас находится, типа, когда он вычитывает новые, офсет, сдвигается, ну, по сути, это указатель на то сообщение, которое ещё там не отработано или отработано последним. Вот это че то не помню. И вот как раз консьюмер
244: Группы ты ты правильно говорила что это для для разделения там групп потребителей и как раз логика в том, что внутри 1 консьюмер группы используется 1 offset это значит, что консюмеры запущены внутри 1 консьюмер групп.
245: Конкурируют друг с другом за сообщения. То есть если мы 2 наших сервиса разных по смыслу засунем в 1 консьюмер группу, то они, читая скаки, будут мешать друг другу, типа 1 будет получать там 1 часть сообщения, другой другую и
246: Они будут тем самым не все их корректно обрабатывать. Поэтому вот в таких ситуациях разные по смыслу, по бизнес смыслу сервисы располагаются в разных консьюмер группах, но внутри 1 консьюмер группы как раз горизонтальное масштабирование запускается вот этих консьюмеров, то
247: Например, сервис уведомлений, да, мы хотим, чтобы быстрее управлять уведомления. Мы увеличиваем там число этих Подов, этого консьюмера, там до 5, допустим, они все ещё живут в 1 консьюмер группе, они конфликтуют друг с другом за сообщения, но это нормально, потому что мы хотим, чтобы они конфликт.
248: Давали и быстрее разгребали. Этот. Надо повторно почитать по поводу заданий, по поводу модиков. Угу. Да, хорошо. Слушай, ну, наверное, тогда по технической части у меня все по теории, по архи.
249: Тоже поговорили по технологиям тоже поговорили. Ларион, может быть у тебя что-то ещё есть? Или на этом остановимся на сегодня? Да, наверное, да, остановимся. Окей, смотри, тогда у нас осталось там времечко. Ещё, если какие-то вопросы по ходу общения Зада появились.
250: Давай их обсудим. Так. Да, на самом деле, наверное, такие более стандартные вопросы. Это по поводу того, как в команде построены процессы, вот как в целом команда построена. Угу. Да, тогда дайте мне сейчас 2 секундочки.
251: Я, у меня батарейка сажается. Быстро подключусь к зарядке, так как построены коман. Процессы в команде. Смотри.