首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Muduo網絡編程示例之八:Timing Wheel 踢掉空閒連接的優雅實現

     編輯:關於C語言

兩種朴素做法的缺陷

  1. 全域掃描:每秒遍歷所有連線檢查 now - lastReceiveTime > 8s,連線數大時開銷大。
  2. 每連線一個 One-shot Timer:頻繁更新 Timer,對 TimerQueue 壓力大。

Timing Wheel(時間輪)原理

利用固定大小(如 8 格)的循環隊列,每格代表 1 秒。指針每秒移動一格,到期格內的連線即被踢掉。新連線或收到資料的連線放入尾部格(剩餘壽命 7 秒)。優點:O(1) 插入/刪除,無需掃描全量,任務均攤到每秒。

連線超時流程圖解

Timing Wheel 初始狀態 1秒後指針移動 連線剩餘壽命遞減 即將被斷開 斷開連線

連線刷新機制

收到資料時,將對應 Entry 移至當前尾部格,壽命重置為 7 秒。多條連線共存於同一格(Hash Set)。

收到資料移至尾部 壽命延長 時間推進

代碼實現亮點:weak_ptr + shared_ptr 引用計數

typedef boost::weak_ptr<TcpConnection> WeakTcpConnectionPtr;

struct Entry : public muduo::copyable
{
    Entry(const WeakTcpConnectionPtr& weakConn) : weakConn_(weakConn) {}
    ~Entry()
    {
        TcpConnectionPtr conn = weakConn_.lock();
        if (conn) conn->shutdown(); // 引用計數歸零時自動斷開
    }
    WeakTcpConnectionPtr weakConn_;
};
typedef boost::shared_ptr<Entry> EntryPtr;
typedef boost::weak_ptr<Entry> WeakEntryPtr;
typedef boost::unordered_set<EntryPtr> Bucket;
typedef boost::circular_buffer<Bucket> WeakConnectionList;

不手動移動 Entry,而是利用 shared_ptr 引用計數:收到資料將 EntryPtr 放入當前桶(計數+1);定時器 push_back 空桶導致舊桶彈出銷毀,EntryPtr 計數-1,歸零觸發析構函數斷開連線。C++ RAUI 自動完成所有資源管理。

關鍵細節

  • TcpConnection::setContext 存儲 WeakEntryPtr(弱引用),避免循環引用。若存強引用 EntryPtr,連線永不會超時(思考題)。
  • onTimer() 僅一行:connectionBuckets_.push_back(Bucket());
  • 代碼見 examples/idleconnection。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved