RxJava-异步流处理

时间:2015-08-05 16:16:54

标签: asynchronous rx-java

我正在使用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);
                    }
                });
    }

1 个答案:

答案 0 :(得分:0)

我建议在尝试使用Subject之前考虑create

如果您希望根据某些分类进行并行处理,可以使用groupByobserveOn来达到预期的效果:

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