api как микросервис / отдельное приложение

397 views
Skip to first unread message

sysadm

unread,
Dec 22, 2017, 12:15:18 PM12/22/17
to RubyOnRails to russian
Всем привет.

Что-то ничего стоящего не могу нагуглить на эту тему. Вопрос не банальный, наверное.
Есть существующее веб приложение и надо рядом запустить API микросервис, который будет пользоваться той же базой, по сути теми же моделями (либо своими, но ежу понятно использующими те же таблицы через AR), но будет работать под другим сервером (допустим puma), возможно физически на другой машине. Какие существуют best practises на эту тему? Если это вообще отдельное приложение с отдельной репой, деплойментом итд итп как решить проблему миграций на той же базе данных? А если, к примеру, основная апликуха сделана на рельсах, а этот микросервис с API вообще на elixir/erlang?

Ребят, поделитесь мыслями как правильно это всё организовать, чтобы с одной стороны всё шустро работало на отдельном сервисе, чтобы не пускать всё с основного кластера unicorn-ов, с другой стороны, чтобы не нагибать особо принципа DRY.

И еще, какие используете инструменты для документирования API для девов? Есть какие-то альтернативы https://swagger.io/swagger-ui/ или на данный момент это лучшее что есть?

Удачного дня.

Konstantin Grabar

unread,
Dec 22, 2017, 3:39:42 PM12/22/17
to RubyOnRails to russian
Привет!

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

Active Record модели, к сожалению, обычно представляют из себя анти-паттерн в виде каши бизнес логики и логики доступа к данным. Поэтому в идеале от этого нужно избавиться. Тогда бизнес логику можно будет вынести в отдельный сервис и обращаться к нему за данными (Монолит -> Сервис с общей логикой <- Микросервис) или же надо через какой-то интерфейс (JSON попривычней и попроще в плане версионности, Protobuf посложнее и значительно быстрее в плане производительности) обращаться к монолиту за данными по тому или иному вопросу (или же, наоборот, в другую сторону: Монолит -> Микросервис). Т.е. самое сложное здесь убрать лапшу из логики и не переборщить при этом, потому что результат может получится отрицательным (при слишком сильном разделении поддерживать изменения в логике по всем микросервисам без ошибок будет не очень просто).

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

По документации ничего необычного не могу посоветовать. Best Practices как-то тоже... У всех своя специфика. Все пилят какую-то свою архитектуру, свой мониторинг (rieman, grafana, datadog), выбирают свои интерфейсы. Надеюсь, чем-то помог :)

пятница, 22 декабря 2017 г., 20:15:18 UTC+3 пользователь sysadm написал:

Илья Плотников

unread,
Dec 23, 2017, 4:43:02 AM12/23/17
to ror...@googlegroups.com
Рельсы это монолит, их особо не распилить на слои dao / service / facade.  Из решений видится автогенерация моделей для соседнего приложения по схеме базы / списку миграций. Rails Admin, например, нормально генерит админку для любого рельсового проекта, думаю там можно подсмотреть механизм и сделать генерацию api.

22.12.2017 20:15, sysadm пишет:
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+un...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/9ef6b54c-809a-41fa-8bb4-fc2dc3a0f49e%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Vladimir Chernyshev

unread,
Dec 23, 2017, 7:09:08 AM12/23/17
to ror...@googlegroups.com
Выделить всё, относящееся к общей части базы, в отдельную зависимость основного приложения и микросервиса. А вообще, общий доступ к базе нарушает принципы микросервисной архитектуры. Постарайтесь перенести всю работу с с этой частью базы в микросервис, а из основного приложения стучаться к нему по АПИ. Или просто сделайте распределённый монолит.

23 дек. 2017 г. 11:42 пользователь "Илья Плотников" <ilyaplo...@gmail.com> написал:
Рельсы это монолит, их особо не распилить на слои dao / service / facade.  Из решений видится автогенерация моделей для соседнего приложения по схеме базы / списку миграций. Rails Admin, например, нормально генерит админку для любого рельсового проекта, думаю там можно подсмотреть механизм и сделать генерацию api.

22.12.2017 20:15, sysadm пишет:
Всем привет.

Что-то ничего стоящего не могу нагуглить на эту тему. Вопрос не банальный, наверное.
Есть существующее веб приложение и надо рядом запустить API микросервис, который будет пользоваться той же базой, по сути теми же моделями (либо своими, но ежу понятно использующими те же таблицы через AR), но будет работать под другим сервером (допустим puma), возможно физически на другой машине. Какие существуют best practises на эту тему? Если это вообще отдельное приложение с отдельной репой, деплойментом итд итп как решить проблему миграций на той же базе данных? А если, к примеру, основная апликуха сделана на рельсах, а этот микросервис с API вообще на elixir/erlang?

Ребят, поделитесь мыслями как правильно это всё организовать, чтобы с одной стороны всё шустро работало на отдельном сервисе, чтобы не пускать всё с основного кластера unicorn-ов, с другой стороны, чтобы не нагибать особо принципа DRY.

И еще, какие используете инструменты для документирования API для девов? Есть какие-то альтернативы https://swagger.io/swagger-ui/ или на данный момент это лучшее что есть?

Удачного дня.
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+unsubscribe@googlegroups.com.

Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/9ef6b54c-809a-41fa-8bb4-fc2dc3a0f49e%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+unsubscribe@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/a7fcd7f5-1526-3a9e-c3c0-cec1f53faf7e%40gmail.com.

Andrius Kairiukstis

unread,
Jan 17, 2018, 5:49:53 AM1/17/18
to RubyOnRails to russian
Интересный вопрос. 

Поднять апи на рельсах несложно. Допустим это будет grape+swagger, это неплохая комбинация. 
Сложнее однако с микросервисом. 

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

Дмитрий Пекаровский

unread,
Mar 6, 2018, 7:23:17 AM3/6/18
to RubyOnRails to russian
Было дело - сделал rake-задачку для запуска в отдельном процессе на синатре. Смысл был в авторизации пользователей, приходящих через websockets-> webstomp-> rabbitmq -> http-auth-plugin -> rake.
Да, не совсем академично, но работает. Главное, чтобы сервис был действительно "микро", то есть один раз отладил и забыл.

Если нужны подробности, то положил такое в lib/tasks

namespace :service do
  desc
'check access for rabbitmq'
  task
:check_access => :environment do
   
CheckAccess.run!
 
end
end

и в app/services положил файлик check_access.rb
class CheckAccess < Sinatra::Base
# тут 90 строк кода с использованием классов для авторизации и аутентификации из основного кода
end




пятница, 22 декабря 2017 г., 19:15:18 UTC+2 пользователь sysadm написал:

leemour

unread,
Mar 7, 2018, 3:17:50 AM3/7/18
to RubyOnRails to russian
Кто уже разбивал рельсы на микросервисы, расскажите пожалуйста про оверхед при синхронном общении микросервисов друг с другом и его минимизацию. Можно делать RPC, HTTP-запросы, есть какие-то еще варианты? Тоже думаю разбить приложение на веб-клиент, api-клиент и сервис с бизнес-логикой и доступом к БД, но предполагаю, что сильно увеличится время ответа на запрос для конечного пользователя.

суббота, 23 декабря 2017 г., 15:09:08 UTC+3 пользователь VolCh написал:
Выделить всё, относящееся к общей части базы, в отдельную зависимость основного приложения и микросервиса. А вообще, общий доступ к базе нарушает принципы микросервисной архитектуры. Постарайтесь перенести всю работу с с этой частью базы в микросервис, а из основного приложения стучаться к нему по АПИ. Или просто сделайте распределённый монолит.
23 дек. 2017 г. 11:42 пользователь "Илья Плотников" <ilyaplo...@gmail.com> написал:
Рельсы это монолит, их особо не распилить на слои dao / service / facade.  Из решений видится автогенерация моделей для соседнего приложения по схеме базы / списку миграций. Rails Admin, например, нормально генерит админку для любого рельсового проекта, думаю там можно подсмотреть механизм и сделать генерацию api.

22.12.2017 20:15, sysadm пишет:
Всем привет.

Что-то ничего стоящего не могу нагуглить на эту тему. Вопрос не банальный, наверное.
Есть существующее веб приложение и надо рядом запустить API микросервис, который будет пользоваться той же базой, по сути теми же моделями (либо своими, но ежу понятно использующими те же таблицы через AR), но будет работать под другим сервером (допустим puma), возможно физически на другой машине. Какие существуют best practises на эту тему? Если это вообще отдельное приложение с отдельной репой, деплойментом итд итп как решить проблему миграций на той же базе данных? А если, к примеру, основная апликуха сделана на рельсах, а этот микросервис с API вообще на elixir/erlang?

Ребят, поделитесь мыслями как правильно это всё организовать, чтобы с одной стороны всё шустро работало на отдельном сервисе, чтобы не пускать всё с основного кластера unicorn-ов, с другой стороны, чтобы не нагибать особо принципа DRY.

И еще, какие используете инструменты для документирования API для девов? Есть какие-то альтернативы https://swagger.io/swagger-ui/ или на данный момент это лучшее что есть?

Удачного дня.
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+un...@googlegroups.com.

Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/9ef6b54c-809a-41fa-8bb4-fc2dc3a0f49e%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+un...@googlegroups.com.

Phil Pirozhkov (pirj)

unread,
Mar 7, 2018, 7:07:33 PM3/7/18
to RubyOnRails to russian
> анти-паттерн в виде каши бизнес логики и логики доступа к данным
> бизнес логику можно будет вынести в отдельный сервис и обращаться к нему за данными

взаимоисключающие параграфы?

Phil Pirozhkov (pirj)

unread,
Mar 7, 2018, 7:16:42 PM3/7/18
to RubyOnRails to russian


On Saturday, December 23, 2017 at 9:43:02 AM UTC, fzn7 wrote:
Рельсы это монолит, их особо не распилить на слои dao / service / facade.

Ну, некоторые потуги в эту сторону есть.
В далёком 2013м году на RUBYSPB 1 была презентация от Nikolay Rizhikov (вот тут первая http://www.sprug.ru/rubyspb-1-slides), но что дальше стало с идеей мне не известно (https://github.com/niquola/cLean-Architecture).
Недавно вышел в опенсорс battle-tested https://github.com/toptal/granite. Документации и примеров пока не много, но начать можно с этого https://github.com/toptal/example_granite_application

Phil Pirozhkov (pirj)

unread,
Mar 7, 2018, 7:33:16 PM3/7/18
to RubyOnRails to russian
Что-то ничего стоящего не могу нагуглить на эту тему. Вопрос не банальный, наверное.
Есть существующее веб приложение и надо рядом запустить API микросервис, который будет пользоваться той же базой, по сути теми же моделями (либо своими, но ежу понятно использующими те же таблицы через AR)

Проронив слово "микросервис", вы увели взгляд читателей в сторону от проблемы.

Предположу, что что через веб-приложение, что через API, который предназначается для мобильных приложений, совершаются одни и те же операции и запрашиваются одни и те же данные. Переписывать веб-приложение с server-rendered на react/vue резона нет, оно и так работает. Примерно так?

О варианте с единой кодовой базой, использующей `respond_to do |format|`, но серверами, приложения на которые деплоятся отдельно не задумывались?

Планируете деплоить эти приложения по отдельности, или синхронные деплои ок?

Илья Плотников

unread,
Mar 9, 2018, 3:32:53 AM3/9/18
to ror...@googlegroups.com
Хорошее замечание по поводу проблемы.
 Эта проблема, она вообще есть на рельсах? Изначально пилить на куски стали из-за монстров. Приложений, компилируемых по 20 минут и стартующих по 40 минут, что превращало разработку в ад.
У ruby /python/php другая парадигма. Инстанс puma стартанет за ~5-15 секунд вне зависимости от количества rb скриптов, которые можно легко менять в рантайме без необходимости перекомпиляции.
Это сильно упрощает задачу и позволяет проводить линейное масштабирование простым copy/paste всего проекта. Внутреннее состояние отсутствует, необходимости в обмене событиями нет, все хранится в базе и актуальное состояние данных всегда доступно всем нодам.

08.03.2018 3:33, Phil Pirozhkov (pirj) пишет:
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на https://groups.google.com/group/ror2ru
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу "RubyOnRails to russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес ror2ru+un...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/7c2af017-cd71-4670-8de0-5f881e8fb16c%40googlegroups.com.

Дмитрий Пекаровский

unread,
Mar 9, 2018, 3:45:20 PM3/9/18
to RubyOnRails to russian
Вопрос не всегда в компиляции. Длительная разработка с меняющимися требованиями... Как вам приложение, замакароненное настолько, что разобраться в нём не могут 5 человек на протяжении года? Приложение в продолжает работать (остановить нельзя, можно только перегружать в аварийном режиме) и все силы команды уходят на обслуживание бизнеса и латание дыр.  Мало того нет ТЗ, поскольку разрабатывалось всё в режиме "Аджайл" и *никто* не может сказать полностью как именно в точности оно работает. Тестов, разумеется, нет. Любая попытка рефакторинга превращается в игру "Морской бой". Единственный выход, который мы нашли - резать на куски и запускать раздельно, предварительно написав отдельный сервис авторизации и роутинга.
И требования, разумеется, продолжают меняться.

//ДП

пятница, 9 марта 2018 г., 10:32:53 UTC+2 пользователь fzn7 написал:

Илья Плотников

unread,
Mar 10, 2018, 1:30:34 AM3/10/18
to ror...@googlegroups.com

Вы сейчас описали обыкновенный рефакторинг и отдачу тех. долга. Микросервисы это про другое. Они про отказоустойчивость, выгодную утилизацию ресурсов и разработку силами 100+ человек. В целом хайп напоминает историю с бигдатой, когда приходили люди и утверждали, что для своих жалких 20 гигабайтных баз им обязательно нужен hadoop кластер чтобы посчитать средний чек


09.03.2018 23:45, Дмитрий Пекаровский пишет:
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/ror2ru/fd6a5780-ab19-4d8c-86ca-1a040ba07270%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages