我正在使用RXJava实现一个简单的数据分析功能,其中主题订阅者异步处理发布到主题的数据,将输出存放到Redis。
当收到消息时,Spring组件将其发布到Observable。为了避免阻止提交,我使用RxJava Async异步执行此操作。
@Override
public void onMessage(final TransactionalMessage message) {
Async.start(new Func0<Void>() {
@Override
public Void call() {
analyser.process(message);
return null;
}
});
}
我在实施其他加工零件时有两个困惑; 1)使用缓冲创建异步Observable 2)根据消息列表上的消息类型计算不同的逻辑并行。
经过长时间的实验,我找到了两种创建Async Observable的方法,但不确定哪种方法是正确的,更好的方法。
方式一,
private static final class Analyzer {
private Subscriber<? super TransactionalMessage> subscriber;
public Analyzer() {
OnSubscribe<TransactionalMessage> f = subscriber -> this.subscriber = subscriber;
Observable.create(f).observeOn(Schedulers.computation())
.buffer(5, TimeUnit.SECONDS, 5, Schedulers.io())
.skipWhile((list) -> list == null || list.isEmpty())
.subscribe(t -> compute(t));
}
public void process(TransactionalMessage message) {
subscriber.onNext(message);
}
}
方式二
private static final class Analyser {
private PublishSubject<TransactionalMessage> subject;
public Analyser() {
subject = PublishSubject.create();
Observable<List<TransactionalMessage>> observable = subject
.buffer(5, TimeUnit.SECONDS, 5, Schedulers.io())
.observeOn(Schedulers.computation());
observable.subscribe(new Observer<List<TransactionalMessage>>() {
@Override
public void onCompleted() {
log.debug("[Analyser] onCompleted(), completed!");
}
@Override
public void onError(Throwable e) {
log.error("[Analyser] onError(), exception, ", e);
}
@Override
public void onNext(List<TransactionalMessage> t) {
compute(t);
}
});
}
public void process(TransactionalMessage message) {
subject.onNext(message);
}
}
TransactionalMessage有不同的类型,所以我想根据类型执行不同的计算。我尝试过的一种方法是根据每种类型过滤列表并单独处理它们,但这看起来很糟糕,我认为不能并行工作。有什么方法可以并行处理它们?
protected void compute(List<TransactionalMessage> messages) {
Observable<TransactionalMessage> observable = Observable
.from(messages);
Observable<String> observable2 = observable
.filter(new Func1<TransactionalMessage, Boolean>() {
@Override
public Boolean call(TransactionalMessage t) {
return t.getMsgType()
.equals(OttMessageType.click.name());
}
}).flatMap(
new Func1<TransactionalMessage, Observable<String>>() {
@Override
public Observable<String> call(
TransactionalMessage t) {
return Observable.just(
t.getMsgType() + t.getAppId());
}
});
Observable<String> observable3 = observable
.filter(new Func1<TransactionalMessage, Boolean>() {
@Override
public Boolean call(TransactionalMessage t) {
return t.getMsgType()
.equals(OttMessageType.image.name());
}
}).flatMap(
new Func1<TransactionalMessage, Observable<String>>() {
@Override
public Observable<String> call(
TransactionalMessage t) {
return Observable.just(
t.getMsgType() + t.getAppId());
}
});
// I sense some code smell in filtering on type and processing it.
Observable.merge(observable2, observable3)
.subscribe(new Action1<String>() {
@Override
public void call(String t) {
// save it to redis
System.out.println(t);
}
});
}
答案 0 :(得分:0)
我建议在尝试使用Subject
之前考虑create
。
如果您希望根据某些分类进行并行处理,可以使用groupBy
和observeOn
来达到预期的效果:
Observable.range(1, 100)
.groupBy(v -> v % 3)
.flatMap(g ->
g.observeOn(Schedulers.computation())
.reduce(0, (a, b) -> a + b)
.map(v -> g.getKey() + ": " + v)
)
.toBlocking().forEach(System.out::println);