我想知道Camel是否可以根据交换内容进行限制。
情况如下:我必须通过肥皂拨打网络服务。其中,发送到该Web服务的参数有一个customerId。问题是如果给定customerId每分钟有超过1个请求,则webservice会发回错误。
我想知道是否可以使用Camel为每个customerId实施限制。因此,不应对所有消息实施限制,而只应对具有相同customerId的消息实施限制。
让我知道如何实现这一点,或者我是否需要澄清我的问题。
答案 0 :(得分:1)
ActiveMQ Message Groups旨在处理此案例。因此,如果您可以在路由中引入JMS队列跃点,那么只需将JMSXGroupId标头设置为customerId即可。然后在另一个路由中,您可以从此队列中使用并发送到您的Web服务以获取您描述的行为。
另见http://camel.apache.org/parallel-processing-and-ordering.html了解更多信息......
答案 1 :(得分:1)
虽然ActiveMQ消息组肯定会处理唯一客户ID的并行处理,但在我的评估中,克劳斯是正确的,为每个唯一的组引入一个限制代表Camel / ActiveMQ的未实现功能。
仅消息组不符合所描述的SLA。虽然每组消息(由客户ID相关)将按顺序处理,每个组有一个线程,但只要请求花费不到一分钟就能收到响应,就不会强制执行每个客户每分钟一个请求的要求。
那就是说,我很想知道是否可以以模拟JIRA中的功能请求的方式组合消息组和节流策略。到目前为止,我的尝试失败了。我正在思考这些问题:
<route>
<from uri="activemq:pending?maxConcurrentConsumers=10"/>
<throttle timePeriodMillis="60000">
<constant>1</constant>
<to uri="mock:endpoint"/>
</throttle>
</route>
但是,节流似乎应用于移动到端点的整个请求集,而不是应用于每个单独的消费者。我不得不承认,我发现这种行为有点惊讶。我的期望是节流将单独应用于每个消费者,这将满足原始问题中的SLA,前提是消息包含JMSXGroupId头中的客户ID。
答案 2 :(得分:0)
我遇到了类似的问题,最后提出了这里描述的解决方案。
我的假设是:
解决方案方法:
Java DSL版本更容易理解:
final AggregationStrategy aggregationStrategy = AggregationStrategies.flexible(Object.class)
.accumulateInCollection(ArrayList.class);
from("direct:start")
.log("Receiving ${body}")
.aggregate(header("customerID"), aggregationStrategy).completionTimeout(60000)
.log("Aggregate: releasing ${body}")
.split(body())
.choice()
.when(header(Exchange.SPLIT_INDEX).isEqualTo(0))
.log("*** Processing: ${body}")
.to("mock:result")
.otherwise()
.to("seda:delay")
.endChoice();
from("seda:delay")
.delay(0)
.to("direct:start");
Spring XML版本如下所示:
<!-- this is our aggregation strategy defined as a spring bean -->
<!-- see http://stackoverflow.com/questions/27404726/how-does-one-set-the-pick-expression-for-apache-camels-flexibleaggregationstr -->
<bean id="_flexible0" class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy"/>
<bean id="_flexible2" factory-bean="_flexible0" factory-method="accumulateInCollection">
<constructor-arg value="java.util.ArrayList" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<log message="Receiving ${body}"/>
<aggregate strategyRef="_flexible2" completionTimeout="60000" >
<correlationExpression>
<xpath>/order/@customerID</xpath>
</correlationExpression>
<log message="Aggregate: releasing ${body}"/>
<split>
<simple>${body}</simple>
<choice>
<when>
<simple>${header.CamelSplitIndex} == 0</simple>
<log message="*** Processing: ${body}"/>
<to uri="mock:result"/>
</when>
<otherwise>
<log message="--- Delaying: ${body}"/>
<to uri="seda:delay" />
</otherwise>
</choice>
</split>
</aggregate>
</route>
<route>
<from uri="seda:delay"/>
<to uri="direct:start"/>
</route>
</camelContext>