如何在复杂的处理流程中对排放进行分组或缓存?

时间:2016-09-20 09:00:35

标签: rx-java

我正在使用RX java进行工具中的大部分处理。基本上我正在研究的工具的想法是:

  • 从某些来源获取有效负载(例如HTML文件)
  • 使用某些特定规则将其拆分为片段。
  • 每个片段可能需要通过异步http调用获取一些额外数据(可以是一个或多个此类调用)
  • 每个片段可能使用完全相同的http调用(端点)
  • 然后使用从http端点返回的数据对片段
  • 执行某些操作
  • 然后将所有已处理的片段组合回有效负载 - 让我们将其称为“已处理的有效负载” 基本上,我描述的流程我已经实现并且工作正常,简单的大理石图显示了基本的想法。

Processing flow

不确定图表是否可读,因此处理的伪代码如下所示:

    Observable.just("SOME_PAYLOAD_AS_STRING")
        .flatMap(payload -> splitToFragmentObservables(payload))  //Getting observables of fragments
        .concatMapEager( //concat all processed fragments
              fragment -> getServiceCallsObservable(fragment) //get service calls for all fragments
                          .flatMap(this::doServiceCall)  // do service call
                          .reduce(new HashMap<>(), (all, result) -> { //reduce results into map
                                all.addAll(result);
                                return all;
                          })
                         .map(all -> newFragmentWithData(fragment, all)) //apply somehow the all service results to my fragment
        )
        .reduce(new StringBuilder(), StringBuilder::append) //reduce all fragments back to string
        .map(StringBuilder::toString);

现在,我正在考虑如何改进某些处理,尤其是HTTP调用。正如您在图中可能注意到的那样,每个片段可以执行完全相同的调用(A,B或C),这是不必要的开销。

我正在寻找一种方法来避免在每个片段中进行相同的服务调用。改善它的最佳方法是什么?组合相同的呼叫,进行呼叫,然后在做最终结果时以某种方式使用它?或者做一些缓存?

3 个答案:

答案 0 :(得分:1)

有一种方法可以缓存Observable生成的结果,并为所有订阅者提供相同的结果。

您有两种选择:

  1. 使用cache运算符。但是,你必须实现缓存失效。
  2. replaypublish运算符一起使用更复杂的解决方案。但是@JakeWharton已经应对了the solution这样的问题。 Here是对这个简单库的解释。
  3. 额外: Here是为Observable发出相同值的问题的另一种解决方案。

    希望,我理解了这个问题并给出了正确答案。

答案 1 :(得分:0)

使用Charles Proxy(或类似代码)查看实际正在进行的呼叫。

如果你使用一个好的Http库进行缓存,那么你的代码可能已经完美了。不要过早地优化!

根据端点具有的缓存规则(以及是否可以更改它们),您可以使用缓存结果来连续调用同一端点。如果您可以控制这些端点,则设置lenient缓存头。

getServiceCallsObservable添加缓存可能是一个更麻烦的解决方案。它还需要是线程安全的,因为getServiceCallsObservable从不同的工作线程调用。 (至少应该,你可能需要添加一些额外的调度,具体取决于你的一些方法的实现和调度细节)

答案 2 :(得分:0)

感谢您的提示。实际上,当我在寻找使用番石榴缓存时,我找到了使用cache运算符的优雅解决方案。

简单地映射到服务结果ObMapable的flatMap运算符

.flatMap(this::doServiceCall)

我改为使用guava cache get方法,当没有可用于给定键的值时执行回调

.flatMap(service -> cache.get(service.getUrl(), () -> doServiceCall(service.getUrl()).cache()))

所以我只是从服务调用中缓存缓存的observable。正在处理的每个新有效负载上正在重新初始化缓存 - 这种缓存仅用于请求。