SOA и RESTful сервисы - примеры?
От: pagrus  
Дата: 09.03.14 20:59
Оценка:
Коллеги,

Недавно довелось услышать идею построения SOA системы на REST сервисах. Мне приходилось строить такую на веб-сервисах, но глубокого опыта использования REST нет — увы.
И поэтому возникают разные вопросы. К примеру, концептуальный — уживаются ли две модели мира, где в одной мир состоит из сервисов, а в другой — из ресурсов? Или практические — как задать чёткий контракт для rest-сервиса? Как на основании этого контракта строить клиентскую часть?

Поделитесь опытом, если вы делали или видели вблизи сервисно-ориентированные системы с использованием REST. Как у вас уживаются REST и SOA? Получается ли элегантное решение, или просто "ловко вкрученная" технология без осязаемой выгоды?

Интересуют не столько рассуждения, сколько практический опыт разрабатываемых, а лучше внедрённых систем.

Спасибо.
Re: SOA и RESTful сервисы - примеры?
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 09.03.14 22:21
Оценка:
Здравствуйте, pagrus, Вы писали:

P>Недавно довелось услышать идею построения SOA системы на REST сервисах. Мне приходилось строить такую на веб-сервисах, но глубокого опыта использования REST нет — увы.


Сайты клепать доводилось? Вот Вам и глубокий опыт использования REST

P>И поэтому возникают разные вопросы. К примеру, концептуальный — уживаются ли две модели мира, где в одной мир состоит из сервисов, а в другой — из ресурсов?


Легко уживаются. Примерно как две перпендикулярные прямые.

SOA — идеология. Состоит в основном из заповедей вида "не делай так" и "не делай эдак". Очень похожа по своей сути на шаблоны объектно-ориентированного программирования.
REST — один из вариантов проектирования интерфейса сервиса.

ООП же не запрещает паттерн Repository? Не запрещает. Вот точно также SOA не запрещает REST.

Если с сервисом проще общаться в терминах ресурсов или если клиенты сервиса просто не умеют ничего другого, кроме HTTP-запросов (как JavaScript, например) — делаем сервису REST-морду. Если интерфейс лучше описывается в RPC-стиле (это обычно означает наличие некоего состояния на стороне сервиса) или если есть какие-то другие предпосылки (скажем, интерфейс обязательно должен быть дуплексным) — делаем сервису SOAP-морду (ну или CORBA-морду, или DCOM-морду). А бывает, что делаем и две морды сразу.

P>Или практические — как задать чёткий контракт для rest-сервиса? Как на основании этого контракта строить клиентскую часть?


А зачем? Все обычно бегут от SOAP-а к REST-у, как раз намучившись с вечно разъезжающимися и дублирующимися схемами и неймспейсами. Т.е. отсутствие строгой типизации считается даже скорее преимуществом REST.

Если клиент и сервис написаны на одном и том же языке программирования — проблема решается расшариванием кода классов запросов/ответов.
А в противном случае URL-ы и форматы запросов/ответов можно и в wiki описать.

P>Интересуют не столько рассуждения, сколько практический опыт разрабатываемых, а лучше внедрённых систем.


Да вот примерно так и живем, как описал выше.
Re: SOA и RESTful сервисы - примеры?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.03.14 04:54
Оценка:
Здравствуйте, pagrus, Вы писали:

P>К примеру, концептуальный — уживаются ли две модели мира, где в одной мир состоит из сервисов, а в другой — из ресурсов?

Нормально уживаются. Для простого скриптинга более-менее всё равно, что за протоколы торчат из сервера (кроме патологических случаев).
Сложности могут начаться, скажем, при попытке реализовать распределённую транзакцию, в которую входят как RPC, так и REST сервисы. В том смысле, что для SOAP, скажем, есть WS-Transactions, а в REST ничего подобного нет, и надо велосипедить руками.

P>Или практические — как задать чёткий контракт для rest-сервиса? Как на основании этого контракта строить клиентскую часть?

Контракт для REST-сервиса обычно состоит из трёх частей:
1. Формат возвращаемых данных (он же описывает разрешённые для записи данные).
Есть разные варианты, которые зависят от того, что за формат вы выбираете для данных REST-сервиса.
Например, для XML можно пользоваться схемами, для JSON — Json-Schema
2. Формат URL. Вообще, предпочтительный способ доступа в REST — это навигация, т.е. в клиенте нежелательно хардкодить способ получения URL к ресурсам. Вместо этого предоставляется способ добраться до всех данных, начиная от одной точки входа, и дальше при помощи разбора возвращаемых данных. Т.е. вместо хардкода типа http://.../GetItemDetail?ItemId=1231231 мы входим на http://.../, где есть <link id="Items" href="/ItemList/"/>, оттуда получаем список ссылок на айтемы, и выбираем нужный нам айтем. Это позволяет в будущем перепроектировать сервис — например, шардить подробности разных товаров по разным сайтам с разными URL.
Но в большинстве случаев форматы запросов всё же документируют — см. например http://en.wikipedia.org/wiki/Open_Data_Protocol
3. Дополнительные ограничения. Ну там — можно ли делать PATCH на объект Order, устанавливая статус Open, если связанный с ним Payment не находится в статусе Complete. Тут, как и в RPC, имеет место разброд и шатание, т.е. спецификации бывают чисто текстовые. По большому счёту, основной способ документации — "метод проб и ошибок", т.е. неприемлемые данные определяются в 4хх ответе, поэтому внятные описания причин проблемы — обязательны.

P>Поделитесь опытом, если вы делали или видели вблизи сервисно-ориентированные системы с использованием REST. Как у вас уживаются REST и SOA? Получается ли элегантное решение, или просто "ловко вкрученная" технология без осязаемой выгоды?

Вблизи я видел мега-технологию APS2. Теоретически, подобное можно было бы сделать и на RPC, но это породило бы много интересных проблем и привело бы к относительно высокой стоимости эксплуатации для ISV.
А сейчас строить приложения для APS2 достаточно легко и приятно, особенно их клиентскую часть. Во многом это благодаря не столько REST, сколько удачному выбору стека для JS-рантайма: почти любой код, написанный без глубокого понимания underlying magic, просто работает как ожидалось.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: SOA и RESTful сервисы - примеры?
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 11.03.14 08:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Сложности могут начаться, скажем, при попытке реализовать распределённую транзакцию, в которую входят как RPC, так и REST сервисы. В том смысле, что для SOAP, скажем, есть WS-Transactions, а в REST ничего подобного нет, и надо велосипедить руками.


Мне кажется, пример не очень удачный. Разве одна из заповедей SOA не звучит как "если тебе захотелось распределенную межсервисную транзакцию, значит, с твоими границами что-то не так"?

(блин, будь проклята эта политика, и сюда пролезла )
Re[3]: SOA и RESTful сервисы - примеры?
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.03.14 07:13
Оценка:
Здравствуйте, scale_tone, Вы писали:

_>Мне кажется, пример не очень удачный. Разве одна из заповедей SOA не звучит как "если тебе захотелось распределенную межсервисную транзакцию, значит, с твоими границами что-то не так"?

Не в курсе про такую заповедь. Но я себе не представляю, как с ней жить. Вот у нас есть сервис приёма платежей, есть сервис доставки товара.
Мы делаем композитный сервис, который принимает заказы. С точки зрения клиента, есть ровно одна операция "заказать".
С точки зрения реализации, есть 2 сервиса. Если платёж сфейлился, то доставку инициировать нельзя. Если доставку инициировать не удалось, то платёж проводить нельзя.
Каким образом "провести границы" так, чтобы обойтись без распределённой транзакции? Запихать всё в один сервис, работающий с одной БД? Это противоречит самой идее SOA.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: SOA и RESTful сервисы - примеры?
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 12.03.14 12:30
Оценка: +1
S>Не в курсе про такую заповедь. Но я себе не представляю, как с ней жить. Вот у нас есть сервис приёма платежей, есть сервис доставки товара.
S>Мы делаем композитный сервис, который принимает заказы. С точки зрения клиента, есть ровно одна операция "заказать".
S>С точки зрения реализации, есть 2 сервиса. Если платёж сфейлился, то доставку инициировать нельзя. Если доставку инициировать не удалось, то платёж проводить нельзя.
S>Каким образом "провести границы" так, чтобы обойтись без распределённой транзакции? Запихать всё в один сервис, работающий с одной БД? Это противоречит самой идее SOA.

Я согласен, что это одна из наиболее известных задачек из области SOA. И что именно ей обычно объясняют необходимость распределенных транзакций.
Но и ее можно решить без использования оных.

Достаточно иметь на борту сервиса Billing локальную транзакционную очередь для исходящих сообщений (это может быть даже не очередь, а таблица в той же реляционной БД, что и бабло юзеров). Billing транзакционно списывает бабло и укладывает сообщение об успехе списывания бабла в эту очередь. В рамках этого же сервиса Billing сидит фоновый обработчик этой очереди, который перепосылает (уже необязательно транзакционно — достаточно гарантированной доставки) сообщения из нее сервису Shipping. Тут возникает возможность задублированности, которая (если это является проблемой) на стороне сервиса Shipping решается путем дедупликации.

Оверхед? Да, само собой, оверхед. Но по сути вся SOA — оверхед в угоду надежности и масштабируемости, нет?
Re[5]: SOA и RESTful сервисы - примеры?
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 12.03.14 13:27
Оценка:
Здравствуйте, scale_tone, Вы писали:

_> В рамках этого же сервиса Billing сидит фоновый обработчик этой очереди, который перепосылает (уже необязательно транзакционно — достаточно гарантированной доставки) сообщения из нее сервису Shipping. Тут возникает возможность задублированности, которая (если это является проблемой) на стороне сервиса Shipping решается путем дедупликации.


Забавно, что именно по такому принципу работают локальные транзакции в MSMQ (технологии, которой уже 17 лет!) при отправке в удаленные очереди.

1. Транзакция начинается.
2. Сообщение укладывается в локальную outgoing queue.
3. Транзакция успешно завершается.
4. MSMQ начинает пытаться доставить сообщение в удаленную incoming-очередь. И может пытаться довольно долго.

Пруфы найти сложно (у MSMQ по жизни проблемы с документацией), но можно. Например:
http://social.msdn.microsoft.com/Forums/en-US/392a098c-23ee-41cb-a26f-bf49dc023cc4/msmq-transactions-make-acknack-messages-obsolete?forum=windowstransactionsprogramming

Или вот тут вскользь упомянуто:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms699870(v=vs.85).aspx
Re[5]: SOA и RESTful сервисы - примеры?
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.03.14 05:45
Оценка:
Здравствуйте, scale_tone, Вы писали:
_>Но и ее можно решить без использования оных.

_>Достаточно иметь на борту сервиса Billing локальную транзакционную очередь для исходящих сообщений (это может быть даже не очередь, а таблица в той же реляционной БД, что и бабло юзеров). Billing транзакционно списывает бабло и укладывает сообщение об успехе списывания бабла в эту очередь. В рамках этого же сервиса Billing сидит фоновый обработчик этой очереди, который перепосылает (уже необязательно транзакционно — достаточно гарантированной доставки) сообщения из нее сервису Shipping. Тут возникает возможность задублированности, которая (если это является проблемой) на стороне сервиса Shipping решается путем дедупликации.


_>Оверхед? Да, само собой, оверхед. Но по сути вся SOA — оверхед в угоду надежности и масштабируемости, нет?

Проблема не в оверхеде, а в том, что вы только что гвоздями прибили сервис биллинга к сервису шиппинга. А SOA — вся про взаимозаменяемость сервисов и возможность построения сложных систем из кирпичиков.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: SOA и RESTful сервисы - примеры?
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 13.03.14 07:28
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


Зачем же, ничего не прибивал

Разгребатель списка фактов успешной оплаты заказов — он же необязательно должен прямо-таки посылать сообщение сервису Shipping. Он может эти факты (опять же, нетранзакционно) публиковать в виде событий. И тогда подписаться на них может и сервис Shipping, и какие-нибудь другие сервисы (e.g. Reporting).
Да, события потом труднее дедуплицировать, но можно же!
Вот Azure Service Bus с недавних пор поддерживает кастомную дедупликацию. Зачем, спрашивается? Именно для таких сценариев.

Или разгребатель может (вновь нетранзакционно) возвращать ответ об успехе внешнему композитному сервису, и тот запустит процесс доставки.

Или сервис Shipping может вообще быть не сервисом, а GUI на JavaScript, который показывает кладовщику список _недоставленных_ заказов, отфильтрованный по фактам успешной оплаты, полученным (например, в виде RSS-feed) из сервиса Billing.

Вариантов куча, и все носят шильдик "SOA-compatible".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.