在继续进行实际的事件处理之前,我试图将事件无穷大的流量(使用反应堆-kafka从kafka中读取)。我的问题是使它在适当的背压下工作。
windowTimeout
和bufferTimeout
似乎是不错的选择,因为它们既可以指定最大大小,又可以限制“流量”低时的等待时间。
首先是windowTimeout
,从中批量写入数据库。但是确实很快就出现了问题: reactor.core.Exceptions $ OverflowException:接收器的信号超出了预期的范围(受限制的队列...)。
然后我切换到bufferTimeout
,但未成功,出现错误 reactor.core.Exceptions $ OverflowException:由于缺少请求而无法发出缓冲区。
我希望以下内容能说明我所遵循的流程:
flux.groupBy(envelope -> envelope.partition)
.flatMap(partitionFlux -> {
final Flux<ConsumedEnvelope> elasticFlux = partitionFlux.publishOn(Schedulers.elastic());
final Flux<List<ConsumedEnvelope>> batchFlux = partitionFlux.bufferTimeout(100, Duration.ofMillis(500))
.concatMap(batch -> {
final ConsumedEnvelope last = batch.get(batch.size() - 1);
return repository.persist(batch) // a)
.then(last.acknowledge()) // b)
.thenReturn(batch);
});
return processing(batchFlux);
})
.subscribe(result -> {
// ...
});
a)repository.persist
在内部什么都不做,只是迭代批处理以创建插入操作,然后返回Mono<Void>
。
b)ConsumedEnvelope.acknowledge()用于Kafka偏移,我只想在成功保留该批处理后执行此操作。全部包裹在concatMap
中,每个分区一次只能处理一个批次。
如上所述,这导致溢出异常。是否有惯用的方式来实现我试图描述的内容?在我看来,这不应该是一件太不常见的任务,但是我是Reactor的新手,很想得到一些建议。
/ d
编辑
我意识到,简单地添加onBackpressureBuffer
确实可以解决这个问题。但是总的来说,有更好的方法吗?
编辑2 ...上述原因当然是由于需求无限而引起的问题,我莫名其妙地错过了。因此,回到最初的问题,或者以某种方式使onBackpressureBuffer不请求未绑定的请求,而仅转发来自下游的请求。