编辑:看到这个更清晰,更准确的问题: RxJava flatMap and backpressure strange behavior
我目前正在用RxJava编写数据同步作业,而且我对反应式编程特别是RxJava库非常新手。
我的工作非常简单我有一个元素ID列表,我调用web服务按ID获取每个元素,进行一些处理并进行多次调用以将数据推送到DB。
我使用1个io线程从WS加载数据,并将数据推送到具有多个io线程的DB。 但是我总是以OutOfMemory错误结束。 我首先想到从WS加载数据比将它们存储在DB中要快。
但是,由于WS调用和DB调用同步调用它们是否应该相互施加背压?
感谢您的帮助。
我的代码看起来很像:
@Test
public void test() {
int MAX_CONCURRENT_LOAD = 1;
int MAX_CONCURRENT_STORE = 2;
List<Integer> ids = IntStream.range(0, 10000).boxed().collect(Collectors.toList());
Observable.from(ids)
.flatMap(this::produce, MAX_CONCURRENT_LOAD)
.flatMap(this::consume, MAX_CONCURRENT_STORE)
.toBlocking().forEach(s -> System.out.println("Value " + s));
System.out.println("Finished");
}
private Observable<Integer> produce(final int value) {
return Observable.<Integer>create(s -> {
try {
if (!s.isUnsubscribed()) {
Thread.sleep(500); //Here I call WS to retrieve data
s.onNext(value);
s.onCompleted();
}
} catch (Exception e) {
s.onError(e);
}
}).subscribeOn(Schedulers.io());
}
private Observable<Boolean> consume(Integer value) {
return Observable.<Boolean>create(s -> {
try {
if (!s.isUnsubscribed()) {
Thread.sleep(10000); //Here I call DB to store data
s.onNext(true);
s.onCompleted();
}
} catch (Exception e) {
s.onNext(false);
s.onCompleted();
}
}).subscribeOn(Schedulers.io());
}
答案 0 :(得分:1)
看来你的WS是基于民意调查的,所以如果你使用fromCallable
代替你的自定义Observable,你得到适当的背压:
return Observable.<Integer>fromCallabe(s -> {
Thread.sleep(500); //Here I call WS to retrieve data
return value;
}).subscribeOn(Schedulers.io());
否则,如果您阻止了WS并阻止了数据库,则可以使用它们相互反压:
ids.map(id -> db.store(ws.get(id)).subscribeOn(Schedulers.io())
.toBlocking().subscribe(...)
并且可能还会留下subscribeOn和toBlocking。