Сервис-ориентированная архитектура и слабая связь против SQL JOINS

Предположим, у нас есть инфраструктура SOA, подобная той, что изображена ниже, и что каждый сервис может работать на другом хосте (это особенно справедливо для двух внесетевых сервисов «веб-сайт» и «платежная система»).

инфраструктура SOA

Очевидно, у нас есть слой данных (постоянства). Предположим, это реализовано через EJB + JPA или что-то подобное.

Если мы хотим объединить данные (в пользовательском интерфейсе) между различными службами, я вижу как минимум пару альтернатив:

  • мы хотим сделать эффективные JOIN на уровне СУБД, поэтому у нас есть пакет (т.е. persistence.package), который содержит все сущности и фасады сеанса (реализация CRUD), которые каким-то образом должны быть разделены (как ?) или для каждой службы. Тем не менее, если я что-то изменю в схеме заказа, я должен повторно развернуть эти пакеты, вводя тесную связь между почти всем. Кроме того, база данных должна быть уникальной и общей.

  • чтобы избежать таких проблем, мы сохраняем пакет сущностей для каждой отдельной службы (например, order.package) и позволяем службам обмениваться данными через какой-либо протокол (soap, rest, esb и т. д.). поэтому мы можем хранить данные локально на каждом хосте (архитектура ничего не делит), и нам не нужно повторно развертывать пакет сущностей. Но этот подход ужасен для интеллектуального анализа данных, поскольку запрос, который должен искать и возвращать коррелированные данные между несколькими службами, будет очень неэффективным (поскольку мы не можем выполнять соединения SQL).

Есть ли лучший/стандартный подход к проблемам, указанным выше?


person gpilotino    schedule 31.03.2013    source источник


Ответы (2)


Основная мотивация для SOA — независимые компоненты, которые могут меняться по отдельности. Вторичная мотивация, как упомянул Марко, — это упрощение системы до более мелких проблем, которые легче решить. Преимуществом различных сервисов является гибкость, а недостатком - больше управления и накладных расходов - эти накладные расходы должны быть оправданы тем, что вы получаете в ответ - см., например, опубликованный мной антишаблон SOA под названием Nanoservices, в котором говорится об этом балансе

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

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

person Arnon Rotem-Gal-Oz    schedule 01.04.2013
comment
это [только] хорошо работает для операционной стороны приложения, так как вам нужно всего несколько элементов из каждой службы. действительно, в этом проблема: обычно нам нужно много данных из разных сервисов, сложный поиск и поиск в реальном времени в пользовательском интерфейсе. Что касается агрегированных отчетов, я вижу очень мало случаев, когда эти данные можно было бы считать неизменяемыми (поэтому обычно денормализация приводит к проблемам с синхронизацией). - person gpilotino; 01.04.2013
comment
Хорошо сказал Армон. Я думаю, что лучше всего для @gpilotino немного почитать о DDD; это очень хорошая книга: infoq.com/minibooks/domain-driven-design -быстро и двигаться оттуда. - person MeTitus; 01.04.2013
comment
Никакая денормализация @gpilotino не вызывает проблем с синхронизацией, не знаю, откуда вы это взяли. Использование другой модели записи и чтения действительно может вызвать проблемы с синхронизацией, но это не имеет ничего общего с денормализованными данными. - person MeTitus; 01.04.2013
comment
Может быть, и ваша книга тоже :) - person MeTitus; 01.04.2013
comment
когда я говорю о необходимости агрегированных отчетов, я на самом деле говорю об отчетах, в которых вы действительно хотите интегрировать данные, которые находятся в службах с большим количеством соединений. Я успешно реализовал SOA во многих системах, в том числе в системах, близких к реальному времени. Также относительно неизменности - любые данные можно сделать неизменяемыми с добавлением версий. ( @Marco :) ) - person Arnon Rotem-Gal-Oz; 01.04.2013
comment
любые данные можно сделать неизменяемыми с добавлением версий, правда. но если вы ссылаетесь на какую-то OLAP-систему (наверное, по звездной схеме), то факт (имхо) в том, что мы можем получить в лучшем случае только фотографию прошлого. чтобы сделать это как можно проще, OLAP не может отвечать на тривиальные запросы, например, сколько заказов принадлежит пользователям, которые фактически живут в Калифорнии (тривиальные в OLTP), если не записывать каждое изменение всех возможных данных, которые могут быть запрошенный (предположим: все). в любом случае, направления, которые вы указали, выглядят хорошо, но я считаю, что такая агрегация в реальном времени является открытой проблемой. - person gpilotino; 02.04.2013

О, мой друг, вы просто усложняете весь сценарий, но это не ваша вина, такие компании, как MSFT, Oracle и другие крупные поставщики программного обеспечения корпоративного класса, любят создавать общую картину чего-то, что намного проще, и они делают это для Причина: вертикальное масштабирование сервисов означает больше лицензий.

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

Итак, у вас есть несколько сервисов в вашей системе: люди, платежная система, заказы, продукты, ERP... на мгновение давайте подумаем, что эти границы правильны с точки зрения бизнес-объектов. Представьте, что эти сервисы — это разные физические отделы вашей компании, а это значит, что они заботятся только о принадлежащих им данных и ни о чем другом.

Тогда вы могли бы сказать, что отдел платежей имеет свою собственную базу данных, то же самое относится и к заказам, конечно, им по-прежнему необходимо взаимодействовать друг с другом, как это делают все отделы, и это можно упростить с помощью открытого суррогатного ключа, сгенерированного системой. Все это означает, что каждая служба поддерживает ссылочную целостность всех своих внутренних сущностей, используя внутренние ключи, но если записи необходимо сделать доступными для других служб, вы можете, например, использовать ключ Guid, например:

введите здесь описание изображения

Службе платежей требуется идентификатор заказа и идентификатор клиента, но эти объекты принадлежат их собственным службам, поэтому вместо совместного использования закрытого ключа (первичного ключа) каждой записи каждая запись будет иметь первичный ключ и суррогатный внешний ключ. службы будут использовать для обмена между ними. Дело в том, что вы должны стремиться создавать слабосвязанные сервисы, каждый со своей «маленькой» базой данных. Каждая служба также должна иметь каждый собственный API, который должен использоваться не только внешним интерфейсом, но и другими службами. Еще одна вещь, которую вам следует избегать, — это использование DTC или другого поставщика управления транзакциями в качестве гаранта транзакций на уровне службы, это то, что можно легко заархивировать, просто используя другой подход к архитектуре.

В любом случае, прочитайте, если вы еще не знакомы с DDD, это даст вам другой обзор того, как создавать программное обеспечение корпоративного класса и, кстати, EJB, убегать от них.

ОБНОВЛЕНИЕ:

Вы можете использовать что-то вроде SOA событий, но давайте не будем усложнять. Зарегистрированный клиент приходит на ваш сайт, чтобы сделать заказ. Ответственная за это служба — Заказы. Список внешних идентификаторов продуктов передается в службу заказов, которая затем регистрирует заказ, в этот момент заказ находится в состоянии «ожидает оплаты», и эта служба возвращает общедоступный идентификатор заказа Guid. Для выполнения заказа покупателю необходимо оплатить товар. Детали платежа отправляются в платежную службу, которая пытается обработать платеж, но для этого ему нужны детали заказа, потому что единственное, что отправил интерфейс, — это идентификатор заказа, и для этого он использует GetOrderDetails(Guid orderId) из API заказа. После завершения платежа служба платежей вызывает еще один метод API заказа PaymentWasCompletedForOrder(Guid orderID). Дайте мне знать, если есть что-то, что вы не получаете.

person MeTitus    schedule 01.04.2013
comment
хорошо, но это все еще не решает больших объединений с проблемами корреляции данных. конечно, я могу хранить внешние ключи в подсистеме заказов, но когда мне нужен список заказов, связанных с именем покупателя, это будет неэффективно (заказы величины учитывают соединение sql), чтобы спросить подсистему людей и так далее. забудьте о ejb и технологиях, моя проблема в том, что если я не хочу синхронизировать/распространять изменения схемы (чтобы вещи оставались слабо связанными), каков наиболее эффективный способ справиться с этим. - person gpilotino; 01.04.2013
comment
можно сказать, просто сохраняйте дополнительные данные для каждого типа отчета (списка данных), которые вам нужны в каждой системе. скажем, в веб-подсистеме продублировать весь список заказов, чтобы пользователи веб-сайта могли их посмотреть. но это создает проблему: как синхронизировать вещи? предположим, я изменил статус заказа в подсистеме заказа, это должно быть отражено на веб-сайте. Таким образом, в этом сценарии денормализованных данных синхронизация стала бы адом интеграции. - person gpilotino; 01.04.2013
comment
Я понимаю, что вы имеете в виду, но проблема в том, что веб-система не является надлежащим отделом, поэтому она не должна существовать. Как я уже сказал, у каждого сервиса должны быть свои уровни API. В домене заказов у ​​вас есть список заказов, связанных с внешним идентификатором покупателя, который затем сопоставляется с частным идентификатором в службе людей, поэтому я не знаю, в чем проблема. - person MeTitus; 01.04.2013
comment
я понимаю. в любом случае, проблема заключается в эффективном поиске и отчете о данных в реальном времени (как в примере со списком моих заказов, который я написал выше) из разбросанных систем. меня устраивает GetThisById(uuid), дело в том, что часто нам нужна агрегация и сложный поиск. т.е. осмысленный список заказов с возможностью поиска в веб-системе и список заказов в системе заказов. веб-система является надлежащим отделом. рассмотрим распространенный сценарий, когда у клиента есть внутренняя система ERP + CRM (внутренняя сеть) и он хочет продвигать продукты из ERP на один или несколько внешних веб-сайтов + поддерживать синхронизацию веб-пользователей с CRM. - person gpilotino; 01.04.2013
comment
Но я не сказал всего этого, у вас есть концепция модели чтения, которая должна быть тем, что питает ваш внешний интерфейс. Скорее нормализованные базы данных для каждой службы, модели чтения являются ненормализованными базами данных. Читайте здесь:gorodinski.com/blog/2012/04/25/ - person MeTitus; 01.04.2013
comment
прежде всего спасибо за ваше время. во-вторых, этот трюк с отображением модели выглядит круто, по крайней мере, для того, чтобы скрыть некоторую связанность. но, имхо, он на самом деле не отличается от какого-то развитого шаблона посредника, который разумно использует технологию подчеркивания (oo + отображение данных), все еще предполагая, что БД уникальна и совместно используется, а также код. - person gpilotino; 02.04.2013
comment
Но в том и разница, что БД не должна использоваться совместно, сервисы должны быть автономными, а это значит, что если один сервис не работает, другие все еще могут выполнять некоторую работу, ожидая в очереди. DDD, SOA... здесь немного сложно объяснить. ИМХО, лучшее, что вы можете сделать, это иметь открытый разум и исследовать другие способы достижения того, что вам нужно. Вы уже делаете это, поэтому вам должно быть довольно просто усвоить эти новые концепции. - person MeTitus; 02.04.2013