Flink 对于TCP背压的处理

当消费者的消费速率低于生产者的发送速率时,会造成背压,此时消费者无法从TCP缓存区中读取数据,因为它无法再从内存池中获取内存,从而造成TCP通道阻塞。生产者无法把数据发送出去,这就使生产者不再向缓存队列中写入数据,从而降低了生产速率。当消费者的消费速率提升且TCP通道不再阻塞时,生产者的发送速率又会得到提升,整个链路运行恢复正常。

TCP的流量控制中有个非常重要的概念——TCP窗口。TCP窗口的大小是可变的,因此也叫滑动窗口。TCP窗口本质上就是描述接收方的TCP缓存区能接收多少数据的,发送方可根据这个值来计算最多可以发送数据的长度

TCP头部比较重要的概念:

  • Sequence Number:包的序号,用来解决网络包乱序问题。
  • Acknowledgement Number:简称ACK(确认序号),用来解决丢包问题。
  • Window:TCP窗口,也叫滑动窗口,用来解决流控。
  • TCP Flag:包的类型,主要用来操控TCP的11种状态机。

Flink实时计算引擎的背压原理

Flink采用Netty发送数据时的高低水位来控制整个链路的背压,是非常好的Netty背压实现实例。大家可能会思考,为何像Dubbo这种RPC框架不采用Netty发送数据时的高低水位来控制整个链路的背压呢?这是因为RPC框架一般只需做请求TPS流量控制即可,而Flink有生产者和消费者,若消费者处理能力非常弱,则生产者需要得到感应,而且此时需要降低生产速率,以缓解消费者的压力。因此Flink无法通过限流来控制整个链路,需要用背压机制来解决。

可以把图中的TaskManager看作一个JVM服务,把Task看作一条线程,一个JVM服务中运行多条Task线程,Task之间通过Netty长连接进行数据交互。

当然,一个TaskManager中只有一个Netty,当Netty接收到数据后,它会把数据拷贝到Task中,拷贝数据需要内存。

图中的Task2作为消费者,其内存的申请及背压处理步骤如下

  1. 先到对应Channel的LocalBufferPool缓冲池中进行申请,若缓冲池中没有可用的内存,且已申请的数量还未达到缓冲池的上限,则向NetworkBufferPool申请内存块,即图中的①和②。
  2. 申请成功后,将其交给Channel填充数据,即图中的③和④。
  3. 若LocalBufferPool缓冲池申请的数量已经达到上限或NetworkBufferPool中的内存已经被用尽,那么当前Task的Netty Channel暂停读取数据。此时数据积压在TCP缓冲区中,导致其TCP窗口的大小变成零,其上游发送端会立刻暂停发送,整个链路进入背压状态。
  4. 在Task1中,当写数据到达ResultPartition写缓存中时,也会向LocalBufferPool缓冲池请求内存块,如果没有可用内存块,则线程状态变成TIME_AWAIT,并且每隔一段时间就会去申请一次,整条线程也会阻塞在请求内存块的地方,达到暂停写入的目的。

那么,问题来了,背压形成后,整条链路什么时候才能恢复正常?

想要恢复正常,只需Task线程在写数据时能正常申请到内存即可。当Task2输出端的处理能力增强后,会调用内存回收方法,将内存块还给LocalBufferPool缓冲池。如果LocalBufferPool缓冲池中当前申请的数量达到了上限,那么它会将该内存块回收给NetworkBufferPool,即图中的⑤和⑥,TCP窗口也会慢慢恢复正常。

通过分析可知,Flink的背压好像与Netty发送数据时的水位控制没太大关系。但是,为了保证服务的稳定,Flink在数据生产端使用Netty发送数据时的高低水位机制来控制整个链路的背压,不向缓存中写太多数据。

如果Netty输出缓冲区的字节数超过了高水位值,则Channel.isWritable()为false,会触发Handler的channelWritabilityChanged()方法。Flink在发送数据时,若发现Channel.isWritable()为false,则不会从发送队列中poll出需要发送的数据,从而形成背压。

当Netty输出缓冲区的字节数降到低水位值以下时,Channel.isWritable()返回true,同时channelWritabilityChanged()方法被触发,Flink在channelWritabilityChanged事件中调用发送方法,这样可以继续发送数据。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菠萝-琪琪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值