即流量控制,有的地方叫作」限流算法」。對於一個系統來講,受限於資源(CPU、內存、帶寬、I/O等等因素)其處理能力是有限的,一旦客戶的流量超過這個限制,每每會引來災難性的後果。所以各類「限流算法」應運而生。比較簡單的有如下幾種模型算法
受限於本人的知識和眼界,目前只瞭解這三種模型,若是從此學習到更多的模型,會補上。多線程
打算分三篇文章來分別探討這幾種模型的原理及其C++實現。本文是第一篇。性能
先介算法原理、接口,最後實現一個可用基於計數器的限流器。學習
我認爲這是最「簡單粗暴的方法」,使用一個累加器來記錄請求次數(即流量),而後按照規定的時間間隔來檢查累加器的數值。這個模型能夠採用「單線程」、「多線程」、「定時器」等多種多樣的手段來實現。
該模型優勢是實現起來簡單,缺點也很明顯:功能太弱、性能不高、不平滑。fetch
接口設計ui
基於C++11標準atom
#ifndef RATE_LIMIT_H #define RATE_LIMIT_H #include <atomic> #include <chrono> class RateLimit { private: // uncopyable RateLimit(RateLimit&&) = delete; RateLimit(const RateLimit&) = delete; const RateLimit& operator=(const RateLimit&) = delete; public: ///< rate: counter per second ///< timeWindow: second(s) RateLimit(uint64_t rate, uint64_t timeWindow) : m_rate(rate) , m_timeWindow(timeWindow * 1000 * 1000) {} bool Consume() { const uint64_t now = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); if (m_time + m_timeWindow <= now) { m_time = now; m_count = 1; return true; } const auto count = m_count.fetch_add(1); return (count < m_rate); } private: std::atomic<uint64_t> m_time = { 0 }; // the start timepoint of the window std::atomic<uint64_t> m_count = { 0 }; // count in one window const std::atomic<uint64_t> m_rate {0}; const std::atomic<uint64_t> m_timeWindow {0}; // micro seconds }; #endif