如何在RxJava RabbitMQ Observable中实现背压?

时间:2016-07-01 10:45:29

标签: rx-java

我是RxJava的新手并尝试从支持无损背压的RabbitMQ队列实现一条Observable消息。我设法从Spring AMQP MessageListener创建一个Observable。这可以在同步环境中处理背压(例如callstack blocking),但是一旦引入多个线程,背压就会超出窗口 - 正如您所期望的那样。课程如下:

import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.stereotype.Component;
import rx.Observable;
import rx.subscriptions.Subscriptions;

import javax.inject.Inject;

@Component
public class CommandExchange {
    private final MessageConverter messageConverter;
    private final ConnectionFactory connectionFactory;

    @Inject
    public CommandExchange(MessageConverter messageConverter, ConnectionFactory connectionFactory) {
        this.messageConverter = messageConverter;
        this.connectionFactory = connectionFactory;
    }

    public <T extends Command> Observable<T> observeQueue(String... queueNames) {
        return Observable.create(subscriber -> {

            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(queueNames);
            container.setMessageListener((MessageListener) message -> {
                T command = (T) messageConverter.fromMessage(message);
                if (!subscriber.isUnsubscribed()) {
                    System.out.println("Being asked for a message.");
                    subscriber.onNext(command);
                }
            });
            container.start();

            Subscriptions.create(container::shutdown);

        });
    }
}

我无法理解如何在不阻塞或缓冲的情况下实现无损背压。使用缓冲是没有意义的,因为Rabbit MQ队列已经是一个缓冲区 - 所以只有当订户准备好它时才应该从队列中消费消息。解决方案是使用基于拉的观察(即停止使用监听器而不是grab a message when there is demand from the subscriber)?如果是这样,处理当前队列中没有消息的情况的最佳做法是什么?

1 个答案:

答案 0 :(得分:1)

是的,我会停止使用监听器并根据需要从队列中获取消息。如果您使用

,则会为您处理请求会计和背压
Observable.create(new SyncOnSubscribe<T>() {...});

SyncOnSubscribe中,你或多或少只是指定了获取一条消息所采取的行动(如果没有等待则不行)。