Reactor - 如何缓冲Rest POST方法中收到的消息

时间:2017-11-23 19:11:03

标签: spring rest spring-boot project-reactor

我是Reactor的新手,我正在尝试更新现有的Spring休息服务以等待接收100条消息,或者直到上次保存之后的时间超过30秒才能保存我接收的消息。

@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) 
public void create(@RequestBody String reqJsonString) throws JsonParseException, JsonMappingException, IOException {

    Flux.just(json).bufferTimeout(100, Duration.ofSeconds(30))
    .publishOn(Schedulers.elastic()).subscribe(list -> {

        LOG.info("size:”+list.size());
        this.save(list);

    });
}

但即使我向其他服务发送了数百条消息,该列表也只包含一条消息。 如何在列表中缓冲POST消息之前将它们保存在一个批处理中?

3 个答案:

答案 0 :(得分:0)

我不确定我是否理解你想做什么,但每当你调用Flux.just(json)时,你都会创建一个新项目的Flux。

你必须创建一个发布者并为每个json调用onNext。 subscribe()部分将不会在POST处理。

这是我从文档中创建的一个简单示例(对不起我的邋))

import reactor.core.publisher.Flux;
import reactor.core.publisher.UnicastProcessor;

import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test {

    private UnicastProcessor<String> hotSource = UnicastProcessor.create();
    private Flux<String> hotFlux = hotSource.publish().autoConnect();


    public void nextItem(String string){
        hotSource.onNext(string);
    }

    public void complete(){
        hotSource.onComplete();
    }

    public static void main(String[] args) throws InterruptedException {
        Test test = new Test();

        // simulate POST calls executed in //
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
        threadPoolExecutor.submit(() -> {
            try {
                //Should get the first two before the first 2s
                test.nextItem("First");
                Thread.sleep(1000);
                test.nextItem("Second");
                Thread.sleep(1000);
                //Should get a single element, since 2.5s will pass between 3rd and 4th
                test.nextItem("Third");
                Thread.sleep(2500);
                //Should get a single element, and the complete
                test.nextItem("Fourth");
                Thread.sleep(3000);
                test.complete();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        test.hotFlux.bufferTimeout(2, Duration.ofMillis(2000))
        .subscribe(
                list -> System.out.println("Got: " + Arrays.toString(list.toArray()))
        );

        threadPoolExecutor.awaitTermination(10L, TimeUnit.SECONDS);
        threadPoolExecutor.shutdown();
    }
}

答案 1 :(得分:0)

有了你的想法,为此你需要像共享Processor那样负责接收结果的东西:

class MyController {    
   private Sink<String> sink;

   MyController() {
      Flux.<String>push(sink -> this.sink = sink)
          .bufferTimeout(100, Duration.ofSeconds(30))
          .publishOn(Schedulres.elastic())
          .subscribe(list -> {

            LOG.info("size:”+list.size());
            this.save(list);

          });
   }



    @RequestMapping(method = RequestMethod.POST)
    @ResponseStatus(value = HttpStatus.OK) 
    public void create(@RequestBody String reqJsonString) throws JsonParseException, JsonMappingException, IOException {
        sink.onNext(reqJsonString);
    }
}

答案 2 :(得分:0)

@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) 
public void create(@RequestBody String reqJsonString) throws JsonParseException, JsonMappingException, IOException {

    Flux.just(json).bufferTimeout(100, Duration.ofSeconds(30))
    .publishOn(Schedulers.elastic()).subscribe(list -> {

        LOG.info("size:”+list.size());
        this.save(list);

    });
}