我有一个很容易制定的请求,但我不能在不泄漏资源的情况下解决这个问题。
我想返回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而不依赖于对等异常的重置或沿着这些线路的某些内容?
答案 0 :(得分:0)
你应该从不尝试自己实现Publisher
接口,因为它归结为让反应流实现正确。这正是您在这里面临的问题。
相反,你应该使用Reactor本身提供的一个生成器运算符(这实际上是一个Reactor问题,没有特定于Spring WebFlux)。
在这种情况下,Flux.create
或Flux.push
可能是最佳候选者,因为您的代码使用某种类型的事件侦听器将事件推送到流中。 See the reactor project reference documentation on that
如果没有更多详细信息,很难为您提供解决问题的具体代码示例。以下是一些指示:
.share()
所有订阅者的事件流