作者:张铁蕾
链接:https://www.zhihu.com/question/49618581/answer/117107570
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

首先,从大的方面说,这篇文档的名字,虽然叫“Backpressure”(背压),但却是在讲述一个更大的话题,“Flow Control”(流控)。Backpressure只是解决Flow Control的其中一个方案。

就像小学做的那道数学题:一个水池,有一个进水管和一个出水管。如果进水管水流更大,过一段时间水池就会满(溢出)。这就是没有Flow Control导致的结果。

而解决Flow Control有几种思路呢?
(1)Backpressure,就是消费者需要多少,生产者就生产多少。这有点类似于TCP里的流量控制,接收方根据自己的接收窗口的情况来控制接收速率,并通过反向的ACK包来控制发送方的发送速率。这种方案只对于cold Observable有效。cold Observable是那些允许降低速率的发送源,比如两台机器传一个文件,速率可大可小,即使降低到每秒几个字节,只要时间足够长,还是能够完成的。相反的例子就是音视频直播,速率低于某个值整个功能就没法用了(这种类似于hot Observable)。
(2)节流(Throttling),说白了就是丢弃。消费不过来,就处理其中一部分,剩下的丢弃。至于处理哪些和丢弃哪些,就有不同的策略,也就是sample (or throttleLast)、throttleFirst、debounce (or throttleWithTimeout)这三种。还是举音视频直播的例子,在下游处理不过来的时候,就需要丢弃数据包。
(3)打包(buffer和window)。buffer和window基本一样,只是输出格式不太一样。它们是把上游多个小包裹打成大包裹,分发到下游。这样下游需要处理的包裹的个数就减少了。
(4)是一种特殊情况,阻塞住整个调用链(Callstack blocking)。之所以说这是一种特殊情况,是因为这种方式只适用于整个调用链都在一个线程上同步执行,这要求中间的各个operator都不能启动新的线程。在平常使用中这种应该是比较少见的,因为我们经常使用subscribeOn或observeOn来切换执行线程,而且有些复杂的operator本身也会内部启动新的线程来处理。另外,如果真的出现了完全同步的调用链,前面的(1)(2)(3)仍然有可能适用的,只不过这种阻塞的方式更简单,不需要额外的支持。

举个例子比较一下(1)和(4)。(4)相当于很多车行驶在盘山公路上,而公路只有一条车道。那么排在最前面的第一辆车就挡住了整条路,后面的车也只能排在后面。而(1)相当于银行办业务时的窗口叫号,窗口主动叫某个号过去(相当于请求),那个人才过去办理。

然后,从细的方面解释一下sample,throttleFirst,debounce。以及onBackpressureBuffer,onBackpressureDrop,onBackpressureBlock和ConnectableObservable(multicast)。

sample就是throttleLast,采样。类比一下音频采样,8kHz的音频就是每125微秒采一个值。sample可以配置成,比如每100毫秒采样一个值,但100毫秒内上游可能过来很多值,选那个值呢,就是选最后那个值。所以它也叫throttleLast。

throttleFirst跟sample类似,比如还是每100毫秒采样一个值,但选这100毫秒内的第一个值。

debounce,也叫throttleWithTimeout,名字里就包含一个例子。比如,一个网络程序维护一个TCP连接,不停地收发数据,但中间没数据可以收发的时候,就有间歇。这段间歇的时间,可以称为idle time。当idle time超过一个预设值的时候,就算超时了(timeout),这个时候可能就需要把连接断开了。实际上一些做server端的网络程序就是这么工作的。每收发一个数据包之后,启动一个计时器,等待idle time过去之后的超时,如果计时器到时之前,又有收发数据包的行为,那么计时器重置,等待一个新的idle time。当计时器到时了,就time out了,这个连接就可以关闭了。debounce的行为,跟这个非常类似,可以用它来找到连续的收发事件之后idle time超时后的timeout事件。

最后还有一个新的问题需要说明。Backpressure有些Observable是支持的,有些不支持。但它们可以通过operator来转化。

onBackpressureBuffer,onBackpressureDrop,onBackpressureBlock就可以把一个不支持Backpressure的Observable转成一个支持Backpressure的Observable(即支持request请求)。但转完之后的策略不太相同。

onBackpressureBuffer是不丢弃数据的处理方式。把上游收到的全部缓存下来,等下游来请求再发给下游。相当于一个水库。但上游太快,就会buffer溢出。

onBackpressureDrop就是当上游来数据的时候,看下游有没有需求,有需求就发给下游,否则上游来的数据就丢掉。

onBackpressureBlock也是看下游有没有需求,下游没有需求,不丢弃,但试图堵住上游的入口(能不能真堵得住还得看上游的情况了),自己并不缓存。

相反,有时候一些operator也能把一个支持Backpressure的Observable变成一个不支持Backpressure的Observable。比如,ConnectableObservable就是这样。它类似于把一条河的主干,在下游分成若干支流(但不太一样的是每条支流的水量都跟主干一样,是拷贝的)。那么很好理解,下游某个支流想对上游产生背压,是不太可能的,它阻止不了水流流向其它支流。

背压(Backpressure)机制的更多相关文章

  1. [转帖]实时流处理系统反压机制(BackPressure)综述

    实时流处理系统反压机制(BackPressure)综述 https://blog.csdn.net/qq_21125183/article/details/80708142 2018-06-15 19 ...

  2. Spark Streaming Backpressure分析

    1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...

  3. RxJava 2.x 使用最佳实践

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76443347 本文出自[赵彦军的博客] 以前写过 Rxjava 系列教程, 如下所 ...

  4. Orleans核心功能

    一.Grain持久性 二.定时器和提醒 三.依赖注入 四.观察者 五.无状态工作者Grains 六.流 一.Grain持久化 1,Grain持久化目标 ①允许不同类型的存储提供者使用不同类型的存储提供 ...

  5. 掘金 Android 文章精选合集

    掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...

  6. Flink之流处理理论基础

    目录 Introduction to Stateful Stream Processing Traditional Data Infrastructures Stateful Stream Proce ...

  7. 4. Spark Streaming解析

    4.1 初始化StreamingContext import org.apache.spark._ import org.apache.spark.streaming._ val conf = new ...

  8. Flink系列(0)——准备篇(流处理基础)

    Apache Flink is a framework and distributed processing engine for stateful computations over unbound ...

  9. Twitter 新一代流处理工具——Heron 该纸币Storm Limitations

    Twitter 新一代流处理工具--Heron 该纸币Storm Limitations (空格分隔): Streaming-Processing Storm Problems scalability ...

随机推荐

  1. 通过js调用android原生方法

    有时候我们有这样一个需求,监听html中控件的一些事件.例如点击html中某个按钮,跳转到别的activity,复制某段文本. 首先是对webview的设置: myWebView = (WebView ...

  2. 更新Xcode后插件失效问题

    Xcode更新后插件会失效,这个时候需要给插件的Info.plist文件添加新Xcode的UUID 一.首先找到更新后的Xcode的DVTPlugInCompatibilityUUID: 打开路径: ...

  3. 手工配置rsyslog配置文件详解

    手工配置 如果您无法通过脚本生成配置文件,这份指导将帮助您通过简单的复制.粘贴手动完成配置. 假定您已拥有root或sudo权限,是在通用的Linux平台使用5.8.0或更高版本的rsyslog,rs ...

  4. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

  5. Django缓存系统设置

    参考: http://lesliezhu.github.io/public/2016/04/19/django-cache.html http://www.opscoder.info/django_c ...

  6. 最新Mac OS X 10.12.1 安装cocoapods及使用详解

    cocoapods官网:https://cocoapods.org 一.什么是CocoaPods 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如 Java 语言的 Maven,nodejs ...

  7. Feature Access

    在ArcGIS Server中发布支持Feature Access地图服务,你需要知道的几点: 所绘制的mxd地图文件中包含的数据,必须来自企业级数据库链接: mxd中包含的所有图层的数据,必须来自同 ...

  8. ffmpeg-20160929-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 5 屏幕横向放大 20 像素 6 屏幕横向缩小 20 像素 S 下一帧 [ -2秒 ] +2 ...

  9. c#程序如何从海康ipserver查询获取DVR设备ip地址

    海康威视提供的ipserver可以记录DVR设备的IP地址,并提供一个7071的端口给客户端查询用,我们在c#程序中可以用海康SDK包中的NET_DVR_GetDVRIPByResolveSvr函数来 ...

  10. Easyui columns列图片移位问题!!!

    InitGrid: function () { $("#list").datagrid({ toolbar: '#tb', url: BanZhengXiaoLuSearch.Aj ...