Reactor / WebFlux实现了一个被动的http新闻自动收报机

时间:2018-04-05 16:56:56

标签: java spring project-reactor

我有一个很容易制定的请求,但我不能在不泄漏资源的情况下解决这个问题。

我想返回application/stream+json类型的回复,其中包含有人发布的新闻事件。我不想使用Websockets,不是因为我不喜欢它们,我只是想知道如何使用流。

为此我需要从我的休息控制器返回一个Flux<News>,一旦有人发布任何内容,就会不断提供新闻。

我的尝试是创建一个发布者:

public class UpdatePublisher<T> implements Publisher<T> {

    private List<Subscriber<? super T>> subscribers = new ArrayList<>();

    @Override
    public void subscribe(Subscriber<? super T> s) {
        subscribers.add(s);
    }

    public void pushUpdate(T message) {
        subscribers.forEach(s -> s.onNext(message));
    }

}

一个简单的新闻对象:

public class News {
    String message;
    // Constructor, getters, some properties omitted for readability...
}

分别发布新闻的端点获取新闻流

// ...

private UpdatePublisher<String> updatePublisher = new UpdatePublisher<>();

@GetMapping(value = "/news/ticker", produces = "application/stream+json")
public Flux<News> getUpdateStream() {
     return Flux.from(updatePublisher).map(News::new);
}

@PutMapping("/news")
public void putNews(@RequestBody News news) {
    updatePublisher.pushUpdate(news.getMessage());
}

这可行,但我无法取消订阅或再次访问任何给定的订阅 - 所以一旦客户端断开连接,updatePublisher将继续推进越来越多的死信道 - 因为我无法打电话订阅上的onCompleted()处理程序。

TL; DL:

是否可以将消息从不同的线程推送到可能无限的Flux上,并且仍然可以根据需要终止Flux而不依赖于对等异常的重置或沿着这些线路的某些内容?

1 个答案:

答案 0 :(得分:0)

你应该从不尝试自己实现Publisher接口,因为它归结为让反应流实现正确。这正是您在这里面临的问题。

相反,你应该使用Reactor本身提供的一个生成器运算符(这实际上是一个Reactor问题,没有特定于Spring WebFlux)。

在这种情况下,Flux.createFlux.push可能是最佳候选者,因为您的代码使用某种类型的事件侦听器将事件推送到流中。 See the reactor project reference documentation on that

如果没有更多详细信息,很难为您提供解决问题的具体代码示例。以下是一些指示:

  • 如果您想要一些类似多播的通信模式,您可能希望.share()所有订阅者的事件流
  • 注意您想要的推/拉/推/拉模型;背压怎么能在这里起作用?如果我们生成更多订阅者可以处理的事件会怎样?
  • 此模型仅适用于单个应用程序实例。如果您希望在多个应用程序实例上工作,您可能希望使用代理查看消息传递模式