C++如何实现线程安全的频率限制器-创新互联

小编这次要给大家分享的是C++如何实现线程安全的频率限制器,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。

成都创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:做网站、成都网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的大新网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

很早以前,在学习使用 Python 的deque容器时,我写了一篇文章python3 deque 双向队列创建与使用方法分析。最近需要压测线上服务的性能,又不愿意总是在 QA 那边排队,于是需要自己写一个压测用的客户端。其中一个核心需求就是要实现 QPS 限制。

于是,终究逃不开要在 C++ 中实现一个线程安全的频率限制器。

设计思路

所谓频率限制,就是要在一个时间段(inteval)中,限制操作的次数(limit)。这又可以引出两种强弱不同的表述:

  • 强表述:在任意一个长度等于设定的时间段(interval)的滑动窗口中,频率限制器放行的操作次数(count)都不高于限制次数(limit)。
  • 弱表述:在一组长度等于设定的时间段(interval)且紧密相连的固定窗口中,每一个窗口里频率限制器放行的操作次数(count)都不高于限制次数(limit)。

不难发现,强表述通过「滑动窗口」的方式,不仅限制了频率,还要求了操作在时间上的均匀性。前作的频率限制器,实际上对应了这里的强表述。但实际工程中,我们通常只需要实现弱表述的频率限制器就足够使用了。

对于弱表述,实现起来主要思路如下:

当操作计数(count)小于限制(limit)时直接放行;

单线程实现

在不考虑线程安全时,不难给出这样的实现。

struct ms_clock {
 using rep = std::chrono::milliseconds::rep;
 using period = std::chrono::milliseconds::period;
 using duration = std::chrono::duration;
 using time_point = std::chrono::time_point;

 static
 time_point now() noexcept {
 return time_point(std::chrono::duration_cast(
   std::chrono::steady_clock::now().time_since_epoch()));
 }
};
} // namespace __details

class RateLimiter {
 public:
 using clock = __details::ms_clock; // 1.

 private:
 const uint64_t limit_;
 const clock::duration interval_;
 const clock::rep interval_count_;

 mutable uint64_t count_{std::numeric_limits::max()}; // 2.a.
 mutable clock::rep timestamp_{0};     // 2.b.

 public:
 constexpr RateLimiter(uint64_t limit, clock::duration interval) :
 limit_(limit), interval_(interval), interval_count_(interval_.count()) {}

 RateLimiter(const RateLimiter&) = delete;  // 3.a.
 RateLimiter& operator=(const RateLimiter&) = delete; // 3.b.
 RateLimiter(RateLimiter&&) = delete;   // 3.c.
 RateLimiter& operator=(RateLimiter&&) = delete; // 3.d.

 bool operator()() const;
 double qps() const {
 return 1000.0 * this->limit_ / this->interval_count_;
 }
};

bool RateLimiter::operator()() const {
 auto orig_count = this->count_++;
 if (orig_count < this->limit_) { // 4.
 return true;
 } else {
 auto ts = this->timestamp_;
 auto now = clock::now().time_since_epoch().count();
 if (now - ts < this->interval_count_) { // 5.
 return false;
 }
 this->timestamp_ = now;
 this->count_ = 1;
 return true;
 }
}

另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


当前名称:C++如何实现线程安全的频率限制器-创新互联
标题来源:http://myzitong.com/article/ddjiic.html