在Project Reactor中对订阅的使用者参数的调用是否顺序进行?

时间:2019-02-25 02:20:13

标签: project-reactor

使用以下代码:

flux.subscribe(consumer)

consumer的调用可能在不同的线程上进行,具体取决于flux的构造方式(例如,使用subscribeOnpublishOn)。是否可以保证即使对consumer的调用可能在不同的线程上进行,这些调用也是顺序的,即每个调用在下一个调用开始之前完成?

下面是一个更具体的示例(使用Reactor-Kafka):

val resultFlux: Flux<Pair<TopicPartition, Long>> = KafkaReceiver
    .create<K, V>(receiverOptions)
    .receive()
    .groupBy { m -> m.receiverOffset().topicPartition() }
    .flatMap { partitionFlux ->
        val parallelRoFlux = partitionFlux
                .publishOn(scheduler)
                .flatMapSequential(::processRecord, parallelism)
        parallelRoFlux.map { ro ->
            acknowledge(ro)
            Pair(ro.topicPartition(), ro.offset())
        }
    }

resultFlux.doOnNext { Thread.sleep(2000); log.info("doOnNext: $it") }
        .subscribe { Thread.sleep(1000); log.info("subscribe: $it") }

产生以下输出片段:

13:44:26.401 [elastic-6] INFO  consumerSvcFlow - Message_5>>>processed
13:44:28.402 [elastic-6] INFO  consumerExecutable - doOnNext: (demo-topic-0, 15)
13:44:29.402 [elastic-6] INFO  consumerExecutable - subscribe: (demo-topic-0, 15)
13:44:29.435 [elastic-8] INFO  consumerSvcFlow - Message_8>>>processed
13:44:31.435 [elastic-8] INFO  consumerExecutable - doOnNext: (demo-topic-0, 16)
13:44:32.436 [elastic-8] INFO  consumerExecutable - subscribe: (demo-topic-0, 16)
13:44:32.461 [elastic-6] INFO  consumerSvcFlow - Message_9>>>processed
13:44:34.462 [elastic-6] INFO  consumerExecutable - doOnNext: (demo-topic-0, 17)
13:44:35.462 [elastic-6] INFO  consumerExecutable - subscribe: (demo-topic-0, 17)
13:44:35.494 [elastic-8] INFO  consumerSvcFlow - Message_15>>>processed
13:44:37.494 [elastic-8] INFO  consumerExecutable - doOnNext: (demo-topic-0, 18)
13:44:38.495 [elastic-8] INFO  consumerExecutable - subscribe: (demo-topic-0, 18)
13:44:38.497 [elastic-6] INFO  consumerSvcFlow - Message_18>>>processed
13:44:40.498 [elastic-6] INFO  consumerExecutable - doOnNext: (demo-topic-0, 19)
13:44:41.499 [elastic-6] INFO  consumerExecutable - subscribe: (demo-topic-0, 19)
13:44:41.539 [elastic-8] INFO  consumerSvcFlow - Message_19>>>processed
13:44:43.540 [elastic-8] INFO  consumerExecutable - doOnNext: (demo-topic-0, 20)
13:44:44.540 [elastic-8] INFO  consumerExecutable - subscribe: (demo-topic-0, 20)

subscribe消费者参数的调用是顺序调用,但是有些调用是在线程[elastic-6]上,而有些调用是在线程[elastic-8]。

1 个答案:

答案 0 :(得分:1)

是的,根据反应流规范,有这样的保证。

首先,调用可能会在与您调用subscribe() 的线程不同的线程上进行。但是所有 consumer 调用都发生在同一线程上。

第二个subscribe(Consumer<T>)方法中的价值使用者实际上被视为onNext中的一个Subscriber信号,因此规范要求将此类调用相对于彼此并{ {1}}和onComplete信号。

编辑:现在您已经添加了一些代码片段,其中有2个线程的事实来自onError内部完成的publishOn。因此,flatMap的每个组可以选择groupBy中不同的Worker(如果有很多)。因此,可以并行执行在这些内部序列中完成的处理。但是,结果在被Scheduler合并时被序列化=> flatMap是顺序的。