当前位置:首页 » 《我的小黑屋》 » 正文

【C++】检测TCP链接超时——时间轮组件设计

27 人参与  2024年09月26日 17:21  分类 : 《我的小黑屋》  评论

点击全文阅读


目录

引言

时间轮思想

设计的核心思路

完整代码

组件接口


个人主页:东洛的克莱斯韦克-CSDN博客

引言

        对于高并发的服务器来说,链接是一种比较珍贵的资源,对不活跃的链接应该及时释放。判断连接是否活跃的策略是——在给定的时间内,该链接上并没有读事件,写事件,异常事件等。如果连接上有事件发生,则刷新链接的活跃时间。

        而时间轮就可以高效的检测链接是否活跃,本文会带大家封装出一个时间轮的组件。

时间轮思想

        时间轮的思想来源于钟表,钟表的时分秒指针指到特定的位置,就代表时间到了。参考钟表的策略,我们可用一个数组代表一个钟表,数组的下标代表时间,指向数组的指针按特定的时间向后移动,指针执行哪个位置,就代表哪个位置的时间到了。

        相应的,指针1秒向后走一格,数组大小为60,这就是分级的时间轮。指针1分钟向后走一格,数组大小为60,这就是时级的时间轮。指针1小时向后走一格,数组大小为24,这就是天级的时间轮。

        也就是说对于时间特别大的场景中,不需要很大的的空间。比如,一个任务在1天3小时15分5秒后超时(假设)只要天级时间轮指向1,就把该任务抛到时级时间轮中...以此类推。

设计的核心思路

        我们需要两个关键的技术——析构函数,智能指针shared_ptr。

【C++】智能指针——auto_ptr,unique_ptr,shared_ptr_auto ptr-CSDN博客

        在我们上述的阐述中,任务是有超时时间的,当时间轮的指针指向这个任务时,说明时间到了,我们该执行这个任务呢——答案是把任务的执行放到析构函数里。

        时间轮的容器可以用两层vevtor—— std::vector<std::vector<TaskSharedPtr>>。如果指针指向TaskSharedPtr(任务类),就释放该类,该类的析构函数就会指向任务的回调。两次vevtor表示在同一个时间内可能会有多个任务。

        智能指针shared_ptr用于任务类的超时时间刷新,在上文提到的高并发服务的场景中,如果触发了链接中的事件,就需要重新刷新时间,但时间轮的指针是一直向后移动的,任务类的下标迟早会被指到,然后该类就会被析构。

        那么我们可以用shared_ptr管理任务类,并且新shared_ptr被插入时间轮之后正确的位置,有shared_ptr的引用计数在,任务类就不会被析构,时间也相当于刷新了。

完整代码

#include <functional>#include <vector>#include <memory>#include <unordered_map>#include <iostream>#include <unistd.h>using TaskFunk = std::function<void()>;  // 定时任务执行的方法using CleanFunk = std::function<void()>; // 清理资源的回调class TimerTask //任务类{private:    uint64_t _id;        // 任务对象的唯一性标识    uint32_t _timeout_t; // 任务的超时时间    bool _cancel;        // 取消任务为true, 不取消为false    TaskFunk _taskfunk;  // 要执行的任务    CleanFunk _cleanfunk;public:    TimerTask(uint64_t id, uint32_t timeout_t, const TaskFunk &funk)        : _id(id), _timeout_t(timeout_t), _cancel(false), _taskfunk(funk)    {    }    ~TimerTask()    {        if (_cancel == false)        {            _taskfunk();        }        _cleanfunk();    }    void AddCleanFunk(const CleanFunk &func)    {        _cleanfunk = func;    }    uint32_t GetTimeout() // 获取超时时间    {        return _timeout_t;    }    void CancelTask() // 取消任务    {        _cancel = true;    }};class TimerWheel //时间轮{private:    using TaskSharedPtr = std::shared_ptr<TimerTask>;    using TaskWeakPtr = std::weak_ptr<TimerTask>;    size_t _ptr;                                    // 时间轮的指针    size_t _capacity;                               // 时间轮的容量    std::vector<std::vector<TaskSharedPtr>> _wheel; // 时间轮容器    std::unordered_map<uint64_t, TaskWeakPtr> _v;   // 任务id和任务weak_ptr映射的容器,快速索引,使shared_ptr引用计数加一private:    void CleanV(uint64_t id) // 清理_v容器资源的函数    {        auto t = _v.find(id);        if (t != _v.end())        {            _v.erase(id);        }    }public:    TimerWheel(size_t capacity)        : _ptr(0), _capacity(capacity), _wheel(capacity)    {    }    void AddTimerTask(uint64_t id, uint32_t timeout_t, const TaskFunk &funk) // 添加定时任务    {        TaskSharedPtr sp(new TimerTask(id, timeout_t, funk));        TaskWeakPtr wp = sp;        _v[id] = wp;                                                // 向_v中注册        sp->AddCleanFunk(std::bind(&TimerWheel::CleanV, this, id)); // 设置清理_v容器资源的回调        size_t pos = (_ptr + sp->GetTimeout()) % _capacity;        _wheel[pos].push_back(sp);    }    void UpdateTimerTask(uint64_t id) // 更新超时的时间    {        auto t = _v.find(id);        if (t != _v.end())        {            TaskSharedPtr sp = _v[id].lock();            size_t pos = (_ptr + sp->GetTimeout()) % _capacity;            _wheel[pos].push_back(sp);        }    }    void UpdatePtr() // 每隔?时间执行一次    {        _wheel[_ptr].clear();        _ptr++;        _ptr %= _capacity;    }    void CancelTask(uint64_t id) // 取消任务    {        auto t = _v.find(id);        if (t != _v.end())        {            TaskSharedPtr sp = _v[id].lock();            sp->CancelTask();        }    }};

组件接口

AddTimerTask:向时间轮中注册任务,三个参数分别是任务id ,任务的超时时间,任务调用的方法。

在上层一定要确保任务id的唯一性。

UpdateTimerTask:传入任务id, 刷新超时时间

UpdatePtr: 这个接口就是前文说的时间轮的指针,多久调用一次就表示时间轮是一个什么级别的的时间轮

CancelTask:传入任务id,说明该任务在时间到了之后也不会被执行。


点击全文阅读


本文链接:http://zhangshiyu.com/post/164997.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 祖母寿宴,侯府冒牌嫡女被打脸了(沈屿安秦秀婉)阅读 -
  • 《雕花锦年,昭都旧梦》(裴辞鹤昭都)完结版小说全文免费阅读_最新热门小说《雕花锦年,昭都旧梦》(裴辞鹤昭都) -
  • 郊区41号(许洛竹王云云)完整版免费阅读_最新全本小说郊区41号(许洛竹王云云) -
  • 负我情深几许(白诗茵陆司宴)完结版小说阅读_最热门小说排行榜负我情深几许白诗茵陆司宴 -
  • 九胞胎孕妇赖上我萱萱蓉蓉免费阅读全文_免费小说在线看九胞胎孕妇赖上我萱萱蓉蓉 -
  • 为保白月光,侯爷拿我抵了债(谢景安花田)小说完结版_完结版小说全文免费阅读为保白月光,侯爷拿我抵了债谢景安花田 -
  • 陆望程映川上官硕《我的阿爹是带攻略系统的替身》最新章节阅读_(我的阿爹是带攻略系统的替身)全章节免费在线阅读陆望程映川上官硕
  • 郑雅琴魏旭明免费阅读_郑雅琴魏旭明小说全文阅读笔趣阁
  • 头条热门小说《乔书意贺宴临(乔书意贺宴临)》乔书意贺宴临(全集完整小说大结局)全文阅读笔趣阁
  • 完结好看小说跨年夜,老婆初恋送儿子故意出车祸_沈月柔林瀚枫完结的小说免费阅读推荐
  • 热推《郑雅琴魏旭明》郑雅琴魏旭明~小说全文阅读~完本【已完结】笔趣阁
  • 《你的遗憾与我无关》宋怀川冯洛洛无弹窗小说免费阅读_免费小说大全《你的遗憾与我无关》宋怀川冯洛洛 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1