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

Rx java 如何在RxJava RabbitMQ Observable中实现背压?,rx-java,Rx Java,我是RxJava新手,尝试从支持无损背压的RabbitMQ队列实现可观察的消息。我已经成功地从Spring AMQP MessageListener创建了一个可观察的对象。这在同步环境中可以很好地处理背压(例如),但一旦引入多个线程,背压就会消失——正如您所期望的那样。课程如下: import org.springframework.amqp.core.MessageListener; import org.springframework.amqp.rabbit.connection.Conne

我是RxJava新手,尝试从支持无损背压的RabbitMQ队列实现可观察的消息。我已经成功地从Spring AMQP MessageListener创建了一个可观察的对象。这在同步环境中可以很好地处理背压(例如),但一旦引入多个线程,背压就会消失——正如您所期望的那样。课程如下:

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);

        });
    }
}
import org.springframework.amqp.core.MessageListener;
导入org.springframework.amqp.rabbit.connection.ConnectionFactory;
导入org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
导入org.springframework.amqp.support.converter.MessageConverter;
导入org.springframework.stereotype.Component;
进口接收。可观察;
导入rx.subscriptions.subscriptions;
导入javax.inject.inject;
@组成部分
公共类命令交换{
私有最终消息转换器消息转换器;
私有最终连接工厂连接工厂;
@注入
公共命令交换(MessageConverter MessageConverter,ConnectionFactory ConnectionFactory){
this.messageConverter=messageConverter;
this.connectionFactory=连接工厂;
}
公共可观察的observeQueue(字符串…队列名称){
返回可观察。创建(订户->{
SimpleMessageListenerContainer容器=新SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(queueNames);
container.setMessageListener((MessageListener)消息->{
T命令=(T)messageConverter.fromMessage(message);
如果(!subscriber.isUnsubscribed()){
System.out.println(“被要求提供消息”);
subscriber.onNext(命令);
}
});
container.start();
创建(容器::shutdown);
});
}
}

我不知道如何在没有阻塞或缓冲的情况下实现无损反压。使用缓冲是没有意义的,因为Rabbit MQ队列已经是一个缓冲区——因此,只有当订阅者准备就绪时,才应该从队列中使用消息。该解决方案是否更倾向于使用基于拉的可观察性(即停止使用侦听器而改为使用)?如果是这样,处理队列中当前没有消息的情况的最佳做法是什么?

是的,我会停止使用侦听器,并根据需要从队列中获取消息。申请会计和背压都是为您处理的,如果您使用

Observable.create(new SyncOnSubscribe<T>() {...});
Observable.create(新建SyncOnSubscribe(){…});

SyncOnSubscribe
中,您或多或少只需指定为获取一条消息而采取的操作(如果没有消息等待,则无操作)。

需要更多有关此消息的帮助吗?如果您需要,我可以添加更多细节。
public Observable observeQueue(String queueName){Observable.OnSubscribe stateless=SyncOnSubscribe.createStateless(s->{s.onNext((T)rabbitmplate.receiveAndConvert(queueName,-1));};返回Observable.create(stateless).subscribeOn(Schedulers.newThread());}
这很有效,但我不确定在新线程上运行的阻塞观察器是否是这里的最佳实践。