由于业务需求,要对总流量进行限速,做了一个C++版本的实现,基本满足业务要求。有需要的同学自行进行优化。
a. 按特定的速率向令牌桶投放令牌
b. 当桶中有足够的令牌则报文可以被继续发送下去,同时令牌桶中的令牌量按报文的长度做相应的减少;
c. 当令牌桶中的令牌不足时,报文将不能被发送,只有等到桶中生成了新的令牌,报文才可以发送。这就可以限制报文的流量只能是小于等于令牌生成的速度,达到限制流量的目的。

生产者按特定的速率向令牌桶投放令牌;
消费者查看令牌桶的令牌,令牌充足消费相应数量的令牌,令牌不足丢弃相应报文或请求。

瞬时流量过高可以用限流处理,流量一直过载的话要考虑扩容。

class ClimitSpeed
{public:ClimitSpeed(unsigned int speed){m_bExitFlag  = false;m_bStartFlag = false;m_time  = 1000;m_totalByte = speed;m_sumByte = 0;InitializeCriticalSection(&m_rwlock);}~ClimitSpeed(){m_bExitFlag = true;DeleteCriticalSection(&m_rwlock);}void Start(){if (m_bStartFlag){return;}m_bStartFlag = true;_beginthread(threadFeed, 0, this);}bool CanConsume(){return (m_sumByte > 0);}void Consume(unsigned int len){EnterCriticalSection(&m_rwlock);   if (m_sumByte > len){m_sumByte -= len;} else{m_sumByte = 0;}LeaveCriticalSection(&m_rwlock);}
private:static void threadFeed(void* arg);void Feed(){EnterCriticalSection(&m_rwlock);    m_sumByte += m_totalByte;LeaveCriticalSection(&m_rwlock);}bool IsStart(){return m_bStartFlag;}
private:unsigned int m_time;  unsigned int m_sumByte;unsigned int m_totalByte;bool m_bStartFlag;bool m_bExitFlag;CRITICAL_SECTION m_rwlock;
};

测试代码

//
/*
在入口函数中包含 _CrtDumpMemoryLeaks();
即可检测到内存泄露
*/
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
//#ifdef _DEBUG
//#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
//#endif
//
#include "stdafx.h"
#include <math.h>
#include <conio.h>    //for kbhit()
#include <stdint.h>
#include <time.h>
#include <process.h>
#include <Windows.h>
static void EnableMemLeakCheck()
{  int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);  tmpFlag |= _CRTDBG_LEAK_CHECK_DF;  _CrtSetDbgFlag(tmpFlag);
}  class ClimitSpeed
{public:ClimitSpeed(unsigned int speed){m_bExitFlag  = false;m_bStartFlag = false;m_time  = 1000;m_totalByte = speed;m_sumByte = 0;InitializeCriticalSection(&m_rwlock);}~ClimitSpeed(){m_bExitFlag = true;DeleteCriticalSection(&m_rwlock);}void Start(){if (m_bStartFlag){return;}m_bStartFlag = true;_beginthread(threadFeed, 0, this);}bool CanConsume(){return (m_sumByte > 0);}void Consume(unsigned int len){EnterCriticalSection(&m_rwlock);   if (m_sumByte > len){m_sumByte -= len;} else{m_sumByte = 0;}LeaveCriticalSection(&m_rwlock);}
private:static void threadFeed(void* arg);void Feed(){EnterCriticalSection(&m_rwlock);    m_sumByte += m_totalByte;LeaveCriticalSection(&m_rwlock);}bool IsStart(){return m_bStartFlag;}
private:unsigned int m_time;  unsigned int m_sumByte;unsigned int m_totalByte;bool m_bStartFlag;bool m_bExitFlag;CRITICAL_SECTION m_rwlock;
};void ClimitSpeed::threadFeed(void* arg)
{ClimitSpeed* pLimit = (ClimitSpeed*)arg;while(!pLimit->m_bExitFlag){if (pLimit->m_bStartFlag){pLimit->Feed();}Sleep(pLimit->m_time);}
}//生成随机数,模拟接受随机报文长度
int GetIntLH(int low, int hight)
{static int a = 0x100;int seed = rand();srand(static_cast<unsigned>(time(nullptr)) - seed + (a += 50));return seed % (hight - low + 1) + low;
}
typedef struct
{bool* pExitFlag;unsigned int speed;HANDLE thread;
}StrucThreadConsume;//消费者线程
static UINT __stdcall funcrun(void* arg)
{int msgLen = 0;unsigned int sum = 0;StrucThreadConsume* p = (StrucThreadConsume *)arg;//测试生成限流器 B/sClimitSpeed *pclimit = new ClimitSpeed(p->speed);unsigned int tick = GetTickCount();unsigned int tick2 = GetTickCount();pclimit->Start();while(!(*(p->pExitFlag))){tick2 = GetTickCount();if (tick2 - tick >= 1000){printf("thread:%#x, sum:%lu, time:%lu\n", p->thread, sum, tick2 - tick);sum = 0;tick = tick2;}if (!pclimit->CanConsume()){Sleep(2);continue;}msgLen = GetIntLH(64, 1500);pclimit->Consume(msgLen);sum += msgLen;}delete pclimit;pclimit = NULL;printf("thread:%#x funcrun exit\n", p->thread);return 0;
}int main()
{EnableMemLeakCheck();//_CrtSetBreakAlloc(265); bool bExit = false;StrucThreadConsume t1;t1.pExitFlag = &bExit;t1.speed = 20 * 1024 * 1024;StrucThreadConsume t2;t2.pExitFlag = &bExit;t2.speed = 30 * 1024 * 1024;HANDLE thread1 = (HANDLE)_beginthreadex(NULL, 0, funcrun, &t1, CREATE_SUSPENDED, NULL);HANDLE thread2 = (HANDLE) _beginthreadex(NULL, 0, funcrun, &t2, CREATE_SUSPENDED, NULL);t1.thread = thread1;t2.thread = thread2;ResumeThread(thread1);ResumeThread(thread2);char k = 0;while(1){if (_kbhit()){k = _getch();if(k == 'q'){bExit = true;break;}}}printf("main will exit\n");getchar();return 0;
}

测试截图,两个测试线程流量控制在20MB/s和30MB/s

令牌桶限速C++实现相关推荐

  1. 令牌桶 限速_Go 限流器实战系列(2) Token Bucket 令牌桶

    上一篇说到 Leaky Bucket 能限制客户端的访问速率, 但是无法应对突发流量, 本质原因就是漏斗桶只是为了保证固定时间内通过的流量是一样的. 面对这种情况, 本篇文章继续介绍另外一种限流器: ...

  2. 可能要用心学高并发核心编程,限流原理与实战,分布式令牌桶限流

    实战:分布式令牌桶限流 本节介绍的分布式令牌桶限流通过Lua+Java结合完成,首先在Lua脚本中完成限流的计算,然后在Java代码中进行组织和调用. 分布式令牌桶限流Lua脚本 分布式令牌桶限流Lu ...

  3. 流量控制算法-----令牌桶------CBS---CIR

    当前用的最多的流量控制算法时令牌桶限速,今天就简单讲一下令牌桶限速的几种实现方式. 主题思想:通过速度可知的令牌控制速度不可知的数据报文. 令牌桶限速核心思想:通过速度可知的令牌桶来控制速度不可知的报 ...

  4. client-go QPS、Burst和令牌桶

    一.背景 本文基于client-go@v0.16.4 之前业务中有这么一段伪代码: func batchCreateVmi(ds []UserData) {wg := &sync.WaitGr ...

  5. 高并发策略之限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)

    导读 网站高可用指的就是:在绝大多的时间里,网站一直处于可以对外提供服务的正常状态. 一般以"年"为单位来统计,"9"的个数越多,代表一年中允许的不可用时间就越 ...

  6. 限速之令牌桶和漏桶算法

    限速是大型服务里面必备的功能,目的是对并发控制和请求进行限速来保护系统,让系统不会因为单位时间内的请求数量太大,被打爆.对于超过了限速的那些请求,处理方法往往是:直接拒绝服务,排队等待,或者降级处理. ...

  7. 令牌桶实现流量限速实例

    今天继续给大家介绍QoS.本文使用华为eNSP模拟器,完成了QoS中令牌桶技术实现的流量限速. 阅读本文,您需要有一定的QoS基础,如果您对此还存在疑惑,欢迎查阅我博客内的其他文章,相信您一定会有所收 ...

  8. 接口限流算法:漏桶算法令牌桶算法

    工作中对外提供的API 接口设计都要考虑限流,如果不考虑限流,会成系统的连锁反应,轻者响应缓慢,重者系统宕机,整个业务线崩溃,如何应对这种情况呢,我们可以对请求进行引流或者直接拒绝等操作,保持系统的可 ...

  9. 令牌桶算法和漏桶算法有什么区别_高并发之限流,到底限的什么鬼 (精品长文)...

    你可能知道高并发系统需要限流这个东西,但具体是限制的什么,该如何去做,还是模凌两可.我们接下来系统性的给它归个小类,希望对你有所帮助. google guava中提供了一个限流实现: RateLimi ...

最新文章

  1. java支持泛型_Java自学-泛型 支持泛型的类
  2. python脚本在命令行中传递参数(附字符查找小案例)
  3. mysql查询数据库第一条记录_SQL获取第一条记录的方法(sqlserver、oracle、mysql数据库)...
  4. plsql提示列快捷键_plsql常用快捷键
  5. .view-content:overflow:hidden 大错误
  6. 一种由视频和音频共同驱动的说话人脸合成方法简介
  7. 西电计算机学院嵌入式所,祝贺计算机科学与技术学院张亮老师团队论文被顶级期刊TNNLS录取...
  8. lpad用法 oracle,oracle lpad 的用法
  9. 关于STC单片机“假死”状态的判别和处理方法
  10. 张桂梅PK清华副教授:不要站在高楼上,傲慢地指着大山
  11. HDU 5869 Different GCD Subarray Query (数学gcd+树状数组离线查询)
  12. 神舟GX8的强冷模式,其他神船伙伴也可以试一试
  13. 超级机器人大战阿尔法php,超级机器人大战α流程攻略 机战Alpha外传分支多线路攻略(9)...
  14. 利用MomentJS 绘制日历
  15. 链路层协议——以太网协议
  16. Junit的先后执行顺序
  17. Oracle数据库踩的坑
  18. adm怎么下bt连接_小型会议室音响设备怎么连接?学习下
  19. SPI接口原理与配置
  20. 关于eclipse或者Android studio直接运行项目到蓝叠模拟器

热门文章

  1. 如何使用格式刷格式多段文字
  2. JS实现瀑布流布局(动态新增数据)
  3. 阿里云盘 Mac 客户端测试版 v2.1.8
  4. java设计模式之代理(转)
  5. 计算机中丢失pcomm.dll,dpcomm.dll(缺失dpcomm.dll文件修复工具)V1.0 最新版
  6. [附源码]Python计算机毕业设计SSM基于协同过滤算法的甜品推荐系统(程序+LW)
  7. 我的世界java版怎么用结构方块_结构方块怎么用 我的世界结构方块使用方法-游侠网...
  8. 入门java-学习markdown语法
  9. 苹果蓝牙耳机怎么接电话_苹果蓝牙耳机哪种好?音质最佳的五大爆款耳机
  10. “二分查找”算法的时间复杂度