FISCO BCOS流量控制策略

发布时间:2021-04-22 来源:本站


流量控制是保证分布式系统稳定性、健壮性、可用性的重要一环,为了提供更稳定可靠、柔性可用的服务,FISCO BCOS引入了流量控制功能,《FISCO BCOS流量控制实现》一文介绍了FISCO BCOS引入流量控制的原因及其实现功能。本⽂将进一步为⼤家揭秘FISCO BCOS流量控制原理及策略。
 

3种常用流量控制算法


分布式系统积累了很多流量控制⽅案,计数器、漏桶(Leaky Bucket)、令牌桶(Token Bucket)是其中最简单、实⽤的流量控制算法,在介绍FISCO BCOS流量控制原理之前,我们先来看看这些常⽤的流量控制算法。


基于计数器的流量控制算法


该算法使用计数器统计一段时间内的请求数目,并在计数器超过指定阈值时,拒绝剩余请求,计数器周期性清零。


 


基于计数器的流量算法


由于该算法仅限制了一段时间内的请求总量,没有限制请求速率,因此无法均衡系统资源使用,在某些情况下甚至"无法承担保护系统的责任"。


假设某系统采用了基于计数器的流量控制方法,计数器清理周期设置为10秒,系统每秒最多可处理1万请求,计数器阈值为10万请求,若恶意攻击者在计数器请求总量很小时,瞬时并发发送10万个请求,这10万个请求均会被接收,系统将面临崩溃风险。


漏桶算法和令牌桶算法
 
漏桶算法和令牌桶算法是限制数据传输速率、请求速率的实用算法,两者基本工作原理如下图:



 
漏桶算法


请求进入漏桶→漏桶以一定速率出水→漏桶满后,直接拒绝后续请求


令牌桶算法


    ●向一定容量的令牌桶中加入令牌


    ●如果令牌桶满,则无法添加新令牌


    ●新请求到来时,先尝试获取令牌,若没有拿到令牌,则阻塞或直接返回;若拿到令牌,则取出令牌,系统处理请求


    ●支持动态变更令牌添加速率以实时控制处理速率
 

FISCO BCOS流量控制算法选择考量

 
通过以上介绍可知,基于计数器的流量控制算法没有限制请求速率,无法均衡系统资源使用;漏桶算法限制了请求处理和响应速率,但不灵活,无法应对突发请求场景;令牌桶算法则通过限制请求流入速率,可应对瞬时突发流量,下表对这三种流量控制算法做了综合对比:


 


通过表格可看出,相较基于计数器的流量控制算法和漏桶算法,令牌桶算法在流量控制效果、灵活性方面均有优势,可同时满足FISCO BCOS请求速率限制和网络流量限制的要求,因此FISCO BCOS最终选择了令牌桶算法来实现流量控制功能。
 
FISCO BCOS流量控制策略

 
参考Guava RateLimiter,FISCO BCOS实现了一套同时支持请求速率限制和网络流量限制功能的流量控制策略。

 


流量控制模块架构图

 

FISCO BCOS支持从节点和群组两个维度对流量进行控制,两者实现原理基本一致,本节将以节点流量控制为例,详述其实现原理。

 

区块链节点初始化时,先根据配置文件中配置的请求速率限制flow_control.limit_req和出带宽网络流量限制flow_control.outgoing_bandwidth_limit为节点和群组创建并初始化RateLimiter。

 

初始化RateLimiter时,会根据速率限制计算令牌更新的时间间隔,设请求速率限制为m_rate_limit,则每隔m_permitsUpdateInterval = 1000/m_rate_limit毫秒会增加一个令牌。

 

在区块链节点处理RPC请求或发送区块消息包之前,首先会尝试获取令牌:


    ●访问节点级别的流量控制模块,尝试获取令牌,若获取失败,则拒绝请求、延迟发送区块;


    ●访问群组级别流量控制模块,尝试获取所在群组的令牌,若获取失败,同样拒绝请求、延迟发送区块,获取成功则可以处理请求、发送区块

 

    ●RateLimiter中维护了当前令牌数目m_currentStoredPermits,为了不影响系统性能,FISCO BCOS采用了令牌延迟更新的策略,即并不实时更新m_currentStoredPermits,当且仅当某请求获取不到令牌时,才会尝试更新m_currentStoredPermits。

 

令牌更新公式如下:


increasedPermits = (double)(now - m_lastPermitsUpdateTime) / m_permitsUpdateInterval;
m_currentStoredPermits = std::min(m_maxPermits, m_currentStoredPermits + increasedPermits);


 

其中now是当前时刻,m_lastPermitsUpdateTime时上一次令牌更新时刻,m_permitsUpdateInterval是令牌更新平均时间间隔,m_maxPermits是令牌桶的最大容量。
 
tryAcquire接口是RateLimiter对外暴露的主要接口,请求可调用该接口尝试获取令牌。


当该接口返回true时,表明请求尝试获取令牌成功,该请求可被处理;


当该接口返回false时,表明请求尝试获取令牌失败,请求会被拒绝或阻塞。
 
设某请求尝试获取requiredPermits个令牌,主要处理流程如下:


    ●若当前令牌桶中的令牌数m_currentStoredPermits不小于requiredPermits,则更新m_currentStoredPermits为m_currentStoredPermits-requiredPermits,并返回true,请求可被处理,否则转后续流程;


    ●根据当前时间和上一次令牌桶更新时间,更新令牌数m_currentStoredPermits;


    若更新后的令牌数m_currentStoredPermits不小于requiredPermits,则同步骤1,更新m_currentStoredPermits为m_currentStoredPermits-requiredPermits,并返回true,请求可被处理,否则拒绝或阻塞请求。
 

小结


本文对比分析了计数器、漏桶、令牌桶3种常用流量控制算法,说明了FISCO BCOS选择令牌桶作为流量控制算法的考量及FISCO BCOS流量控制实现策略。

 

流量控制对于维持系统稳定性、健壮性、可用性至关重要,不仅仅适用于区块链、分布式系统和海量服务场景,同样适用于通用的业务场景。

 

目前FISCO BCOS的QoS优化工作仍在持续进行中,欢迎大家共同探讨交流。

-------------------------

本文转自:FISCO BCOS 开源社区公众号,欢迎加小助手微信【FISCOBCOS010】进技术交流群。
点击阅读原文 

分享至: