我是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)?如果是这样,处理当前队列中没有消息的情况的最佳做法是什么?
答案 0 :(得分:1)
是的,我会停止使用监听器并根据需要从队列中获取消息。如果您使用
,则会为您处理请求会计和背压Observable.create(new SyncOnSubscribe<T>() {...});
在SyncOnSubscribe
中,你或多或少只是指定了获取一条消息所采取的行动(如果没有等待则不行)。