От части вы правы: мы получили дополнительный сервис в поддержку, протокол у нас собственный.
Тут правда надо заметить, что мы скрываем, что у нас вообще используется Кафка от пользователей, для них сервис скорее похож на amazon sqs, Yandex queues и так далее.
Пункт 3 не совсем понятен: почему становится труднее, такого в статье не утверждается.
Редпанда нам нравится и у нас есть планы на переход на нее, о чем однажды, думаю, будет следующая статья
Дисбаланс подключений действительно возможен. Но нагрузка от таких подключений на databus не очень большая, а подключений много, поэтому в среднем распределение достаточно равномерное. Поэтому в этом плане у нас есть упрощение: сложной балансировки нет.
События действительно могут перепутаться, также, да, в текущей схеме может быть ситуация, когда часть событий останется в умершем ДЦ. Но мы намеренно не предоставляем гарантий порядка событий на данном этапе эволюции нашей системы и требуем от клиентов устойчивости к нарушениям порядка и дублям.
Camel для нашего случая не рассматривали. Наша шина представляет собой просто механизм обмена событий и не предполагает наличие логики по их обработке или трансформации. В будущем - возможно вокруг нее добавится какой-то механизм для обработки, тогда мы посмотрим на доступные варианты, может быть и camel, хотя он не очень ложится в стек нашей компании (из-за java/kotlin)
Да, формат конечно же похож на описание protobuf, спасибо за замечание
Единый реестр есть, в статье есть кратко про это. Все схемы событий при деплое попадают в этот реестр и потом мы валидируем изменения на допустимость и публикуемые события на корректность
Паттерн outbox у нас поддерживается. Есть реализация клиента databus, которая на самом деле пишет события в отдельную специальную таблицу в той же базе данных, что и остальные сущности, а потом фоновый отдельный воркер перекладывает их в databus. Для клиента все работает атомарно внутри одной транзакции.
Написать общую библиотеку можно, но потом сложно следить за тем, чтобы ее своевременно обновляли и чтобы например, когда мы включаем один кластер или переводим его на другие адреса, или когда мы хотим заменить кафку на что-то другое, то это прошло бы незаметно для клиента.
Наш же сервис - это фасад.
Сама по себе шина не так сложна, фактически в ней просто websocket соединение вида pub/sub, где клиент может сказать в какие топики он хочет писать, а из каких читать.
Пока жив коннект от клиента - мы держим коннект в кафку. Плюс под капотом пара дополнительных штук типа набирания батча для клиента на консьюминге и так далее.
Общая задача была в том, чтобы защитить клиентов от знания о внутренней технологии, ее топологии и не дать совершать невалидные действия, так что решение в этом плане оправдывает себя
Но тут дело ведь не только в потере сообщений. Консьюмеры не получат ничего, что было опубликовано в момент, когда они были отключены: например, в следствии бага, а момент редеплоя или каких-либо других работ.
А какую топологию кластера натса вы в итоге используете?
Мы в своих внутренних исследованиях обнаружили нестабильность работы NATS при кластером сетапе в 5 нод и использовании Jetstream (один баг даже зарепортили). В частности это проявляется в нестабильном создании стримов, "отключении" консьюмеров.
Также нас не очень устроила скорость работы Jetstream: при 300-400k RPM латенси записи начинает очень сильно уступать кафке. Ну и с масштабированием стримов тоже есть вопросы.
Общий наш вывод в том, что nats без Jetstream хорош, но с ним - пока слишком молод и нестабилен.
Разница между RPC и REST лишь в понятийной области. Вполне можно использовать REST, но обычно сложно уложить многообразие действий в парадигму REST, да и не особо нужно.
В нашем случае, да, у каждого сервиса свой набор эндпоинтов, которые вызываются другими. Другие сервисы, разумеется, знают в какой сервис они шлют запросы.
Производительность ниже, чем если бы это был монолит, но зато мы можем разрабатывать такие системы отдельно друг от друга. Также никто не отменяет кэши и другие оптимизации
Это один из паттернов возможных обменов. Например, недоступна шина, сервисы живут на одном физическом сервере или имеется особый характер данных, скажем вы выгружает видео файл и передаёте его другому сервису.
В общем смысле ответ таков. Каждый сервис занимается своими задачами, поддерживается отдельной командой и отвечает за выделенную предметную область.
Но различные процессы в одних сервисах могут запускаться как реакция на изменения в других. Именно для отправки сообщений о подобных изменениях и нужна шина данных
Не факт. Большая часть современной нагрузки - это нагрузка на сеть, когда процесс, обрабатывая входящий запрос делает какое-то количество исходящих запросов к другим системам, базам данных, очередям и прочему
Очень интересно, жду продолжения. Все, что связанно с логистикой и складом - супер интересная тема, ведь в ней айти встречается с реальным миром как никогда близко
Согласен с вами. Своим комментарием я имел в виду, что пульсар, имея в основе систему хранения логов, похож в этом на Кафку, но в отличие от нее добавляет поверх ещё ряд функций: отложенные сообщения, отсутствие ограничения на число консьюмеров и другое. Все то, что в случае с кафкой пришлось бы реализовывать самостоятельно. Но все это правда не бесплатно с точки зрения надёжности
Спасибо за комментарий.
От части вы правы: мы получили дополнительный сервис в поддержку, протокол у нас собственный.
Тут правда надо заметить, что мы скрываем, что у нас вообще используется Кафка от пользователей, для них сервис скорее похож на amazon sqs, Yandex queues и так далее.
Пункт 3 не совсем понятен: почему становится труднее, такого в статье не утверждается.
Редпанда нам нравится и у нас есть планы на переход на нее, о чем однажды, думаю, будет следующая статья
Спасибо, на RSocket посмотрим обязательно.
Дисбаланс подключений действительно возможен. Но нагрузка от таких подключений на databus не очень большая, а подключений много, поэтому в среднем распределение достаточно равномерное. Поэтому в этом плане у нас есть упрощение: сложной балансировки нет.
События действительно могут перепутаться, также, да, в текущей схеме может быть ситуация, когда часть событий останется в умершем ДЦ. Но мы намеренно не предоставляем гарантий порядка событий на данном этапе эволюции нашей системы и требуем от клиентов устойчивости к нарушениям порядка и дублям.
Camel для нашего случая не рассматривали. Наша шина представляет собой просто механизм обмена событий и не предполагает наличие логики по их обработке или трансформации. В будущем - возможно вокруг нее добавится какой-то механизм для обработки, тогда мы посмотрим на доступные варианты, может быть и camel, хотя он не очень ложится в стек нашей компании (из-за java/kotlin)
Да, формат конечно же похож на описание protobuf, спасибо за замечание
Единый реестр есть, в статье есть кратко про это. Все схемы событий при деплое попадают в этот реестр и потом мы валидируем изменения на допустимость и публикуемые события на корректность
Выше уже ответили на многие вопросы.
У нас есть таймауты на подключения, keep-alive сообщения, чтобы убедиться, что клиент жив.
Также у нас есть реестр схем событий, благодаря которому мы можем валидировать контракты как в момент попытки деплоя сервиса, так и при публикации
По-сути, переизобрели :)
Можете чуть подробнее раскрыть вопрос про разрыв соединения и схему данных?
Паттерн outbox у нас поддерживается. Есть реализация клиента databus, которая на самом деле пишет события в отдельную специальную таблицу в той же базе данных, что и остальные сущности, а потом фоновый отдельный воркер перекладывает их в databus. Для клиента все работает атомарно внутри одной транзакции.
Написать общую библиотеку можно, но потом сложно следить за тем, чтобы ее своевременно обновляли и чтобы например, когда мы включаем один кластер или переводим его на другие адреса, или когда мы хотим заменить кафку на что-то другое, то это прошло бы незаметно для клиента.
Наш же сервис - это фасад.
Сама по себе шина не так сложна, фактически в ней просто websocket соединение вида pub/sub, где клиент может сказать в какие топики он хочет писать, а из каких читать.
Пока жив коннект от клиента - мы держим коннект в кафку. Плюс под капотом пара дополнительных штук типа набирания батча для клиента на консьюминге и так далее.
Общая задача была в том, чтобы защитить клиентов от знания о внутренней технологии, ее топологии и не дать совершать невалидные действия, так что решение в этом плане оправдывает себя
Спасибо за интересную статью.
А что происходит после завершения проекта? Кто занимается поддержкой всего, что создала v-team, когда ее участники разошлись по новым командам?
Но тут дело ведь не только в потере сообщений. Консьюмеры не получат ничего, что было опубликовано в момент, когда они были отключены: например, в следствии бага, а момент редеплоя или каких-либо других работ.
Это не является проблемой?
Кластер же позволяет вам проводить работы на nats, пересетапливать сервера без простоя и т.д.
Как сейчас вы обеспечиваете бесперебойную работу?
Также, как я понимаю, вам не требуется персистивность сообщений после публикации продюсером?
А какую топологию кластера натса вы в итоге используете?
Мы в своих внутренних исследованиях обнаружили нестабильность работы NATS при кластером сетапе в 5 нод и использовании Jetstream (один баг даже зарепортили). В частности это проявляется в нестабильном создании стримов, "отключении" консьюмеров.
Также нас не очень устроила скорость работы Jetstream: при 300-400k RPM латенси записи начинает очень сильно уступать кафке. Ну и с масштабированием стримов тоже есть вопросы.
Общий наш вывод в том, что nats без Jetstream хорош, но с ним - пока слишком молод и нестабилен.
Разница между RPC и REST лишь в понятийной области. Вполне можно использовать REST, но обычно сложно уложить многообразие действий в парадигму REST, да и не особо нужно.
В нашем случае, да, у каждого сервиса свой набор эндпоинтов, которые вызываются другими. Другие сервисы, разумеется, знают в какой сервис они шлют запросы.
Производительность ниже, чем если бы это был монолит, но зато мы можем разрабатывать такие системы отдельно друг от друга. Также никто не отменяет кэши и другие оптимизации
Это один из паттернов возможных обменов. Например, недоступна шина, сервисы живут на одном физическом сервере или имеется особый характер данных, скажем вы выгружает видео файл и передаёте его другому сервису.
Файл это просто носитель информации
В общем смысле ответ таков. Каждый сервис занимается своими задачами, поддерживается отдельной командой и отвечает за выделенную предметную область.
Но различные процессы в одних сервисах могут запускаться как реакция на изменения в других. Именно для отправки сообщений о подобных изменениях и нужна шина данных
Не факт. Большая часть современной нагрузки - это нагрузка на сеть, когда процесс, обрабатывая входящий запрос делает какое-то количество исходящих запросов к другим системам, базам данных, очередям и прочему
Очень интересно, жду продолжения. Все, что связанно с логистикой и складом - супер интересная тема, ведь в ней айти встречается с реальным миром как никогда близко
Ещё один вариант, который очень простой, но довольно рабочий - использование байесовского классификатора.
Можно классифицировать на любое число классов, очень быстро работает
Можно сделать nack и настроить в пульсаре redelivery timeout: тогда оно будет предоставлено через заданный интервал времени
Да, все верно, используем в том числе отложенные сообщения
Согласен с вами. Своим комментарием я имел в виду, что пульсар, имея в основе систему хранения логов, похож в этом на Кафку, но в отличие от нее добавляет поверх ещё ряд функций: отложенные сообщения, отсутствие ограничения на число консьюмеров и другое. Все то, что в случае с кафкой пришлось бы реализовывать самостоятельно. Но все это правда не бесплатно с точки зрения надёжности