RxJava一个发布服务器的多个使用者
我正在编写一种带有缓存的中间件HTTP代理。工作流程是:RxJava一个发布服务器的多个使用者,java,caching,rx-java,reactive-streams,backpressure,Java,Caching,Rx Java,Reactive Streams,Backpressure,我正在编写一种带有缓存的中间件HTTP代理。工作流程是: 客户端请求此代理获取资源 如果缓存中存在resurce,代理将返回它 如果未找到资源,代理将获取远程资源并返回给用户。在加载数据时,代理将此资源保存到缓存中 我的界面具有用于远程资源的Publisher流、接受Publisher保存的缓存,以及接受Publisher作为响应的客户端连接: //远程资源 接口资源{ Publisher-fetch(); } //缓存 接口缓存{ 可完全保存(发布者数据); } //客户端响应连接 接口连接{
Publisher
流、接受Publisher
保存的缓存,以及接受Publisher
作为响应的客户端连接:
//远程资源
接口资源{
Publisher-fetch();
}
//缓存
接口缓存{
可完全保存(发布者数据);
}
//客户端响应连接
接口连接{
可完成发送(发布者数据);
}
我的问题是,在向客户机发送响应时,我需要将这个字节缓冲区流延迟保存到缓存中,因此客户机应该负责从远程资源请求bytebyfer
块,而不是缓存
我尝试使用Publisher::cache
方法,但这对我来说不是一个好选择,因为它将所有接收到的数据都保存在内存中,这是不可接受的,因为缓存数据的大小可能只有几GB
作为解决方法,我创建了主题
,由从资源
收到的下一个项目填充:
私有最终缓存;
私人最终连接输出;
可完成代理(资源资源){
Subject mirror=PublishSUbject.create();
返回Completable.mergeArray(
out.send(res.fetch().doOnNext(镜像::onNext),
cache.save(mirror.toFlowable(BackpressureStrategy.BUFFER))
);
}
是否可以重用相同的
Publisher
,而不在内存中缓存项目,并且只有一个订阅者负责向Publisher请求项目?我可能遗漏了一些内容(添加了关于我的Publisher
界面版本不同的注释)
但是,在概念上,我是这样做的
我将简化接口以处理整数
:
// remote resource
interface Resource {
ConnectableObservable<Integer> fetch();
}
// cache
interface Cache {
Completable save(Integer data);
}
// client response connection
interface Connection {
Completable send(Integer data);
}
输出:
Caching 1
Caching 2
Caching 3
Caching 4
Sending 1
Caching 5
Caching 6
Caching 7
Caching 8
Caching 9
Sending 2
Caching 10
. . .
更新 根据您的评论,在您的案例中,尊重背压似乎很重要 假设您有一个
发行商
在某个地方尊重背压,您可以将其转换为可流动的
,如下所示:
Flowable<T> flowable = Flowable.fromPublisher( publisher );
我无法理解你说的话:所以客户端应该负责从远程资源而不是缓存请求ByteByfer块。!@bubbles我指的是背压:
Publisher
has method请求(长n)
正在从Publisher
请求下一个n
项目的数量。客户端的连接
比缓存
慢,因此只有连接
应该负责从资源的远程Publisher
请求下一个n
字节缓冲
项目的数量在RxJava的版本中是这样的吗?我在2.x上,Publisher
只有一个方法:Publisher.subscribe(订阅anks以获取答案。我使用的是RxJava2,Publicher
接口是reactivestreams1.0.0
的一部分,请看,实际上与您的接口存在一些不匹配,因为Cache
和Connection
接受Publisher
(让我们使用T
而不是整数和缓冲区),而不是纯整数。因此问题在于发行商的订阅者在onSubscribe()之后可能会从订阅
请求下一个项目
call@Kirill在您的链接中,Publisher
有一个方法:Publisher::subscribe
。您的问题引用了一个方法Publisher::cache
,而您的代码似乎引用了Publisher::doOnNext
。我找不到这两个方法中的任何一个。在我对问题的原始评论中,我谈到了subscribration
Publisher
,而不是Publisher
本身,它有方法请求(长)
:另外,我在问题中提到了背压是重要的一部分,缓存作为消费者要快得多,因此它填充了可连接的可流动的的缓冲区,在发送到慢速连接之前,内存将充满项目,这是主要问题(请参阅原始问题).@KirillConnectableFlowable
尊重来自最慢使用者的背压,您可以通过调用Flowable.publish(int-bufferSize)来控制其缓冲区的大小
。假设您的基础资源/发布服务器也考虑了背压,那么就不会有内存消耗问题。谢谢,我刚刚验证过,可连接的发布服务器考虑了来自最慢的用户的背压。
Flowable<T> flowable = Flowable.fromPublisher( publisher );
ConnectableFlowable<T> flowable = Flowable.fromPublisher( publisher ).publish();
out.send(flowable); // calls flowable.subscribe()
cache.save(flowable); // calls flowable.subscribe()
flowable.connect(); // begins emitting values