Комментарии 24
Но из самой статьи не понятен профит разбивания коризны/каталога/шины событий на микросервисы. Будущие проблемы видны, выгоды не видны.
Кроме того, ваши измышления противоречат 12 factor apps в части логгирования. К вашему сведению, логи пишутся в консоль и никуда более, и далее транслируются в систему типа ELC. Иные решения, в стиле вашего ActivityLogger — грех.
И насчет логирования (пишется с одним «г» :-). Я прекрасно знаю как логируются данные и что такое ELK (не ELC). Сервис ActivityLogger — не более чем пример опроса событий. Если Вы знакомы с упоминаемой книгой Хорсдала, Вы поймете, почему я привел именно этот пример.
«не нравится идея генерировать «болванку» для сервиса на основе yml и клиента как отдельную сборку» — хотелось бы аргументов
«Хорошо подходит для web-приложений, где нужно предоставлять большое количество разнородных и часто меняющих структуру данных» — чем же для этого плох сваггер? Он как бы считается пром стандартом, и структур данных в спеке можно много наобъявлять, и менять их легко. Но в отличие от вашего решения сваггер унифицирует апи и предоставляет бесплатно транспорт, валидацию и документацию.
«Если Вы знакомы с упоминаемой книгой Хорсдала, Вы поймете, почему я привел именно этот пример.» — знаком. Но там имхо существует путаница между журналированием и логированием (да, спасибо за поправку). Если ваш мета сервис именно _журналирует_, то вопросов нет. Но у вас же сервис назван Logger-ом — логично предположить из названия, что он «логирует»
Кроме того остался вопрос межсервисной коммуникации — как в вашей архитектуре её осуществлять, вручную? но это не правильно.
И насчет сваггера — я не говорю что он плох. Но давайте рассмотрим процесс разработки чего-то (назовем Service) с использованием OpenApi:
1. Описать структуру сервиса и моделей данных.
2. Сгенерировать ServiceApi, реализовать в нем нужную функциональность (лучше конечно функциональность вынести в отдельный сервис и внедрить его в ServiceApi как зависимость)
3. Сгенерировать ServiceApiClient.
4. Сконфигурировать использование ServiceApiClient во всех нужных местах приложения.
5. Если планируем обращаться к ServiceApi из UI, то нужно либо как-то передать в UI конфигурации конечных точек, либо организовать редиректы, сконфигурировать CORS и т.д.
Хотя признаю, бесплатное, из коробки, документирование, валидация и другие плюшки это приятно :-)
Теперь с использованием описанного в статье подхода:
1. Разработать интерфейс IService
2. В микросервисе разработать реализацию этого сервиса и опубликовать как конечную точку (пара строк в Setup)
3. Зарегистрировать IService как зависимость во всех нужных местах и использовать ее привычным образом (в общем-то для ServiceApiClient нужно сделать ровно то же самое, но в отличие от OpenApi мы можем все интерфейсы собрать в одну сборку)
4. Ну с собственно редиректы на микросервисы из главного приложения (если нужно).
Наше приложение Microcommerce с использованием OpenApi получается несколько более громоздким, не так ли?
Разработать интерфейс IService
Зарегистрировать IService как зависимость во всех нужных местах и использовать ее привычным образом
Тут на сцену выходит .NET Remoting, оказывается MS уже в 2000 году придумала фреймворк для микросервисов в внедрила его в рантайм .NET по самые помидоры.
Ох, история развития ПО действительно идёт по спирали.
Разрабатывать интерфейс IService не нужно, он генерируется из спеки и является своего рода низкоуровневой деталью реализации апи, используемой фреймворком.
Публиковать реализацию так же не нужно, она сама «публикуется».
ServiceApi и ServiceApiClient генерирует тулза — бесплатно, для этого не нужно прилагать умственных усилий. Вся конфигурация сервера сводится к запуску хттп листенера с указанием урла и прописывания миделварей точно так же как у вас (CORS и т.п ), ни какие редиректы не нужны. Банально прописывается реализация для сгенерированных заглушек и всё. При этом архитектура самого сервера не завязана на DI, а доменную модель можно делать как вам больше нравится — на DI или глобальных переменных или как-то ещё.
Что касается клиента, то ServiceApiClient на C# в данном случае (я пишу на другом ЯП, раньше писал на C#) нужен исключительно для интеграционных и функциональных тестов на апи. И его конфигурация так же сводится к указанию корневого урла сервера.
Далее, если мы не планируем обращаться к ServiceApi из веб приложения браузера, а планируем его юзать из внутренних сервисов, мобильных клиентов и, например, дектопа — то нам нужен не сваггер, а grpc как более универсальная, мощная, надёжная и простая технология. Сваггер — только для веба.
Конкретно для веба генерируется fetch-клиент и типы структур данных сервиса на typescript. Поэтому фронтенд программисту не нужно думать о конечных точках, обработке ошибок хттп и т.п. вещам касательно транспорта. Он получает полностью типизированный и рабочий апи, сгенерированный из спеки OpenApi, так же как и ServiceApiClient для тестов — ServiceApiClient.Foo(Bar). Фронтенд программист так же участвует в разработке спеки, внося в неё требуемые ему фичи. В вашем же случае типизация апи на стороне клиента и транспорт делаются вручную и поддерживаются в актуальном состоянии через боль и слёзы.
В вашем же случае типизация апи на стороне клиента и транспорт делаются вручную и поддерживаются в актуальном состоянии через боль и слёзы.
Ну на самом деле не все так печально с типизацией на стороне клиента
habr.com/ru/post/266899
вы просто взрыв из прошлого, удивлен что не вспомнили генерации прокси из webservice в VS2008
Есть ситуация когда управляющий сервис, а с ним общается вся пачка из 200-т воркеров на постоянной основе, надо обновлять не останавливая работу. Мы поднимаем обновленный сервис и переводим на него работу всех воркеров.
Таже самая ситуация в обратную сторону, при переносе сервиса-воркера на другой сервер или виртуалку сервисы работающие с фермой должны отслеживать их перемещение. Если это один сервис, то еще ничего, а если их десяток?
У вас есть N ДЦ, в которых подняты идентичные системы, но обслуживают разные регионы. Например Европа-США-Азия, очень распространенный вариант размещения для увеличения отзывчивости. Предположим падает сервис или хостер уронил виртуалку или произошел непредвиденный сбой. Самый простой способ чтоб на время сбоя сервисы поднятые в других ДЦ перехватили работу павшего собрата, до момента его подъема.
А как Вы решаете проблему передачи данных на несколько сервисов, со сложным роутингом, размещением сервисов в региональных ДЦ? В случае постройки работы проекта на WebApi разворот потоков данных фермы достаточно не простая задача.
Мне кажется в вашем случае нужна звездообразная архитектура. Как вариант — использование какого-либо MQ-сервера, RabbitMq или ApachMq. Я разрабатывал подобные системы взаимодействия приложений, и даже есть Nuget-пакет для этого, хоть меня и критикуют за велосипеды :-). Если Вам интересно — пишите в личку, я поделюсь наработками.
Мне иетересно, пробовали ли вы Microsoft Orleans? Как на меня отличнейшее решение для 90% случаев. Но тут я пока только как теоретик, пару раз кластер подымал — проще ничего нету.
Первое что в голову приходит
- Строгая типизация реквестов через интерфейсы со скоростной сериализацией
- Автоматическая балансировка вплоть до миграции воркера на другую машину с состоянием (естественно надо persistanse писать)
- Автоматический failover
- Поддержка кластерного singleton по умолчанию. Удобно, знеаете ли, знать что три машины не колбасят ту же задачу или данные.
- Distributed cache в силу того что работает предыдущий пункт
- Встроенные события/потоки/таймеры/remainders
- Discovery
Можно еще покопать, но как на меня профит очевиден: пишите себе на чистом .NET забыв о swagger. Расслабляетесь от балансировки "микросервисов", от толпы не нужных инстансов. Не конфигурируете кеши, очереди (ну без них не всегда можно).
Сумбурно как-то так
Для балансировки нагрузки и масштабирования я имею опыт использования ApacheMq
Посмотрел, что-то больно на Java мир завязано. И разве это не брокер сообщений?
Я бы его больше к этому проекту сравнивал: https://github.com/dapr/dapr
В общем-то те же фичи что описаны Вами для Microsoft Orleans, но плюс еще кросс-платформенность
.NET Core давно кросплатформенный как бы.
А насчет кросс-платформенности — я имел в виду взаимодействие с приложениями на java, php и т.д. Хотя Вы правы, лучше использовать чистый .Net Core, если нет каких-то экстраординарных кейсов.
.NET Core: Взаимодействие микросервисов через Web api