Apache camel 使用驼峰路由策略设置sqs高优先级/低优先级路由消费者的优雅方式?

Apache camel 使用驼峰路由策略设置sqs高优先级/低优先级路由消费者的优雅方式?,apache-camel,amazon-sqs,Apache Camel,Amazon Sqs,我有两个SQS队列:一个用于低优先级,另一个用于高优先级消息。该逻辑意味着不要触摸低优先级队列上的消息,除非高优先级队列为空 SuspendLowPriorityRoutePolicy suspendLowPriorityRoutePolicy = new SuspendLowPriorityRoutePolicy(LOW_PRIORITY_ROUTE_ID, camelContext); from(UriBuilder.buildSqsUri(sqsProperties)).

我有两个SQS队列:一个用于低优先级,另一个用于高优先级消息。该逻辑意味着不要触摸低优先级队列上的消息,除非高优先级队列为空

SuspendLowPriorityRoutePolicy suspendLowPriorityRoutePolicy = new SuspendLowPriorityRoutePolicy(LOW_PRIORITY_ROUTE_ID, camelContext);

        from(UriBuilder.buildSqsUri(sqsProperties)).routeId(LOW_PRIORITY_ROUTE_ID)
                .log(LoggingLevel.INFO, log, "NON-PRIORITY: ${body}");

        from(UriBuilder.buildPrioritySqsUri(sqsProperties)).routeId(HIGH_PRIORITY_ROUTE_ID)
                .routePolicy(suspendLowPriorityRoutePolicy)
                .log(LoggingLevel.INFO, log, "PRIORITY: ${body}");

这两个使用者的
concurrentConsumers
属性都设置为1,这意味着他们将一次处理一条消息

现在,我将这两条路由设置为同时使用队列中的消息。我想要的是,进入高优先级路由的消息触发低优先级路由的停止。为了尝试获得此功能,我尝试使用一种路由策略,在高优先级路由上启动新exchange时停止低优先级队列:

(来自
SuspendLowPriorityRoutePolicy
的片段)

但是,我不确定如何重新启动低优先级消费者。Camel
RoutePolicy
提供的其他钩子允许覆盖
onExchangeDone
,但此时的逻辑应该是仅在高优先级队列为空时重新启动低优先级使用者。我认为没有办法检查队列是否为空,我们可以检查exchange done钩子上的
approximateEnumberOfMessages
属性,但这可能不准确


另一个想法是,有一个定时后台轮询器,它检查
CamelContext
的inFlightRequestsRepository,并且仅当高优先级路由没有机上请求时才重新启动低优先级队列

好吧,我能想到的最简单的方法是,使用高优先级消息,比使用低优先级消息的消费者多得多。这样,高优先级的消息通常会很快被消耗,而低优先级的消息可能会堆积起来,因此必须等待

但是,无论同时处理的高优先级消息有多少,低优先级消费者仍将处理消息


更接近您的用例的是使用

您可以以相同的方式使用两个队列,只需在每个队列的消息上设置不同的JMS优先级。例如,低优先级消息的标准优先级为4,高优先级消息的优先级为8

然后将两个消费者的消息转发到第三个队列。因此,在第三个队列中,高优先级消息和低优先级消息混合到达,但每个消息都具有适当的优先级设置

然后将使用者附加到第三个队列,由于消息优先级,应首先使用高优先级消息。只有当队列不包含高优先级消息时,才会使用低优先级消息

但是,有一些事情需要记住:

  • 使用消息优先级根据需要对队列中的消息重新排序。这会降低包含大量消息的队列的性能
  • 可能必须在您的代理或队列上激活消息优先级。否则,优先权就会被忽略。与您的经纪人一起搜索优先级示例,以检查这一点
  • 我不确定,但我认为JMS连接上也有一些标志来尊重消费者的优先级
  • 您必须将消费者预取保持在较低的水平。如果您的消费者以低优先级预取1000条消息,它会在执行任何其他操作之前处理所有消息。无论是否同时高优先级消息到达队列。预取越大,在处理新到达的高优先级消息之前,可以处理的低优先级消息越多
 @Override
    public void onExchangeBegin(Route route, Exchange exchange) {
        Route lowPriorityRoute = context.getRoute(lowPriorityRouteId);
        ServiceStatus routeStatus = context.getRouteStatus(lowPriorityRouteId);
        if (!routeStatus.isStopped()) {
            try {
                lock.lock();
                log.info("High priority request came in, stopping consumer");
                stopConsumer(lowPriorityRoute.getConsumer());
            } catch (Exception e) {
                log.error("Exception stopping consumer " + e);
                handleException(e);
            } finally {
                lock.unlock();
            }
        }
    }