Вопрос по web-services, rest – Apache верблюд для объединения нескольких ответов службы REST

6

Я новичок в Camel, и мне интересно, как я могу реализовать приведенный ниже вариант использования с помощью Camel,

У нас есть веб-сервис REST, и предположим, что у него есть две сервисные операции: callA и callB. Теперь у нас есть слой ESB спереди, который перехватывает клиентские запросы, прежде чем перейти к этим фактическим URL-адресам веб-служб.

Теперь я пытаюсь сделать что-то вроде этого - Укажите URL-адрес в ESB, который клиент фактически вызовет. В ESB мы используем компонент Jetty Camel, который просто передает этот сервисный вызов. Итак, допустим, что этот URL будет / my-service / scan /

Теперь, получив этот запрос @ESB, я хочу вызвать эти две конечные точки REST (callA и callB) - & gt; Получите их ответы - resA и resB - & gt; Объедините его в один объект ответа resScan - & gt; вернуться к клиенту.

Все, что у меня есть сейчас -

<route id="MyServiceScanRoute">
<from uri="jetty:http://{host}.{port}./my-service/scan/?matchOnUriPrefix=true&amp;bridgeEndpoint=true"/>
<!-- Set service specific headers, monitoring etc. -->  
<!-- Call performScan -->
<to uri="direct:performScan"/>
</route>

<route id="SubRoute_performScan">
<from uri="direct:performScan"/>
<!--  HOW DO I??
Make callA, callB service calls. 
Get their responses resA, resB.
Aggregate these responses to resScan
 -->
</route>

Ваш Ответ

2   ответа
15

) По моему скромному мнению лучший способ назвать дваindepended Удаленные веб-службы и объединить результаты заключается в:

call services in parallel using multicast aggregate the results using the GroupedExchangeAggregationStrategy

Маршрутизация для решения выше может выглядеть следующим образом:

from("direct:serviceFacade")
  .multicast(new GroupedExchangeAggregationStrategy()).parallelProcessing()
    .enrich("http://google.com?q=Foo").enrich("http://google.com?q=Bar")
  .end();

Обмен перешел наdirect:serviceFacadeResponse будет содержать свойствоExchange.GROUPED_EXCHANGE установить список результатов звонков на ваши сервисы (поиск Google в моем примере).

И вот как вы могли быdirect:serviceFacade до конечной точки причала:

from("jetty:http://0.0.0.0:8080/myapp/myComplexService").enrich("direct:serviceFacade").setBody(property(Exchange.GROUPED_EXCHANGE));

Теперь все HTTP-запросы к URL-адресу службы, предоставляемому вами в ESB с использованием компонента Jetty, будут генерировать ответы, объединенные из двух вызовов к вспомогательным сервисам.

Further considerations regarding the dynamic part of messages and endpoints

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

Вообще говоря - тип маршрутизации, используемый для достижения динамических параметров конечных точек или полезных нагрузок, сильно зависит от компонента, который вы используете для использования веб-сервисов (HTTP, CXFRS, Restlet, RSS и т. Д.). Каждый компонент зависит от степени и способа его динамической настройки.

Если на ваши конечные точки / полезные нагрузки нужно воздействовать динамически, вы также можете рассмотреть следующие варианты:

Preprocess copy of exchange passed to each endpoint с использованиемonPrepareRef вариант конечной точки Multicast. Вы можете использовать его для обращения к пользовательскому процессору, который будет изменять полезную нагрузку перед передачей его конечным точкам многоадресной рассылки. Это может быть хорошим способом создания onPrepareRef с заголовком Exchange.HTTP_URI компонента HTTP.

Use Список получателей (который также предлагаетparallelProcessing как это делает Multicast) для динамического создания URL-адресов конечных точек REST.

Use Разветвитель шаблон (сparallelProcessing включен) разделить запрос на более мелкие сообщения, посвященные каждой услуге. Еще раз этот вариант может работать довольно хорошо сExchange.HTTP_URI заголовок компонента HTTP. Это будет работать, только если обе подуслуги могут быть определены с использованием одного и того же типа конечной точки.

Как вы можете видеть, Camel довольно гибок и предлагает вам различные способы достижения вашей цели. Рассмотрите контекст вашей проблемы и выберите решение, которое подходит вам лучше всего.

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

@Petter На самом деле я хочу сказать, что все параметры URL, передаваемые клиентом, должны передаваться (переноситься), когда я выполняю вызовы служб. В этом примере я вижу жестко закодированный параметр для упрощенной демонстрации (два вызова службы всегда будут с q = foo & amp; q = bar). После прочтения документации Camel я обнаружил, что компонент http может быть полезен в этом отношении ... таким образом я переадресую параметры URL, которые клиент отправил другой конечной точке. Это звучит правильно? Rishi
@Petter Когда я нажимаю на конечную точку REST, это в значительной степени просто URL (запрос GET). Но у меня есть один вопрос, мне нужно, чтобы параметры передавались на отдельные сервисные вызовы. пример:0.0.0.0:8080/myapp/myComplexService?keyword=abc так что это "ключевое слово" параметр должен передаваться в отдельных вызовах службы - & gt;myserver.com/serviceA?keyword=abc & Амп;myserver.com/serviceB?keyword=abc Rishi
Спасибо, что приняли мой ответ. Приветствие также приветствуется: P.
@Rishi, Генрик продемонстрировал это выше. Посмотрите на URI, q = Foo и q = Bar. Это будет представлять ваше ключевое слово = abc.
Хорошая демонстрация многоадресной директивы, Генрик. Однако создается впечатление, что необходимо подготовить полезную нагрузку, а не только URL-адрес запроса к каждой службе. Вы можете сделать это с помощью многоадресной рассылки? Разве не многоадресная передача для одного и того же сообщения в несколько конечных точек?
2

где следует использовать шаблон Content Enricher.Описано здесь

<from uri="direct:performScan"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateRequestAndA"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateAandB"/>
</route>

Стратегии агрегирования должны быть написаны на Java (или, может быть, на каком-нибудь скриптовом языке, Scala / groovy? - но я этого не пробовал).

Стратегия агрегации просто должна быть компонентом, реализующим org.apache.camel.processor.aggregate.AggregationStrategy, который, в свою очередь, требует от вас реализации одного метода:

Exchange aggregate(Exchange oldExchange, Exchange newExchange);

Итак, теперь вы должны объединить запрос с ответом на сервисный запрос на обогащение. Вы должны сделать это дважды, так как у вас есть и callA, и callB. Существуют две предопределенные стратегии агрегации, которые могут оказаться полезными или нет, UseLatestAggregationStrategy и UseOriginalAggregationStrategy. Имена вполне понятны.

Удачи

Спасибо за указатели! Действительно ценю это. Позвольте мне начать чтение с шаблона Content Enricher и так далее. Rishi
Да, это звучит уместно, учитывая, что полезная нагрузка отличается в вызове, а не только в URL. В любом случае, вы не можете злоупотреблять «прямым» транспорт в верблюде. Это чрезвычайно полезно, так как позволяет делать такие вещи и модулировать ваши маршруты, создавать повторно используемые под-маршруты и т. Д. Затраты - это просто вызов метода (или, так сказать, так).
После серии обсуждений с командой мы выяснили, что вариант Enricher будет дорогостоящим в качестве последовательного (и у нас может быть более двух вызовов службы). Сейчас я оцениваю варианты использования: 1. EIP обработчика составных сообщений / Splitter-Aggregator 2. Или EIP с разбрасыванием 3. Или Список получателей со стратегией Agregator. Какой из них подходит для варианта использования? Rishi
Выглядит как в шаблоне списка Multipcast и списка получателей "то же самое"; сообщение направляется нескольким потребителям. Но в этом случае два разных вызова веб-службы (callA и callB) совершенно разные. Поэтому я собираюсь попробовать что-то вроде этого - & lt; split & gt; & lt; to uri = "direct: callA" / & GT; & lt; to uri = "direct: callB" / & GT; & lt; to uri = "seda: aggregateScan" / & GT; & Lt; / разделить & GT; & Л; маршрут & GT; & lt; from uri = "direct: callA" / & gt; & lt;! - Позвонить в службу веб-обслуживания - & gt; & Л; / & маршрут GT; & lt;! - тот же маршрут для B - & gt; & lt;! - маршрут агрегации и стратегия bean ref - & gt; Rishi
Проблема заключается в том, чтобы сохранить запрос и агрегированный ответ на одном и том же маршруте, поскольку вы хотите ответить на вызов HTTP. Наиболее привлекательным вариантом, по-видимому, является receientList с указанной стратегией агрегирования и параметром & quot; parallellProcessing & quot; опция установлена в true. Самое сложное - написать стратегию агрегации, поскольку она может получать ответы в любом порядке. Я ничего не знаю о полезной нагрузке, но она должна быть довольно простой.camel.apache.org/aggregator.html Есть несколько примеров, как объединить несколько ответов, например, наибольшее число в последовательности ответов. Г.Л.

Похожие вопросы