005_针对于go语言中速率限制的思考
在之前的go语言的速率限制这篇文章里,我们尝试了普通的速率限制,和脉冲型速率限制。其中,脉冲型速率限制是放开了限制,里面有3个请求是一次性到达,然后再按照200ms的速度限制的,之前的代码如下所示:
package main import "fmt"
import "time" func main() {
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
limiter := time.Tick(time.Millisecond * 200) for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
} burstyLimiter := make(chan time.Time, 3)
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
} go func() {
for t := range time.Tick(time.Millisecond * 200) {
burstyLimiter <- t
}
}() burstyRequests := make(chan int, 5)
for i := 1; i <= 5; i++ {
burstyRequests <- i
}
close(burstyRequests)
for req := range burstyRequests {
<-burstyLimiter
fmt.Println("request", req, time.Now())
}
}
最终的输出是下面这样,可以看到下面那段输出的前三次输出,时间几乎没差,这是一次脉冲型速率限制:
request 1 2018-04-17 12:57:02.823975218 +0800 CST m=+0.205374957
request 2 2018-04-17 12:57:03.024067833 +0800 CST m=+0.405476106
request 3 2018-04-17 12:57:03.220187209 +0800 CST m=+0.601603847
request 4 2018-04-17 12:57:03.420175881 +0800 CST m=+0.801601050
request 5 2018-04-17 12:57:03.622105704 +0800 CST m=+1.003539485 request 1 2018-04-17 12:57:03.622191244 +0800 CST m=+1.003625029
request 2 2018-04-17 12:57:03.622210962 +0800 CST m=+1.003644748
request 3 2018-04-17 12:57:03.622223153 +0800 CST m=+1.003656939
request 4 2018-04-17 12:57:03.82356235 +0800 CST m=+1.205004724
request 5 2018-04-17 12:57:04.024178896 +0800 CST m=+1.405629826
那我们如果想实现另一种脉冲型速率限制怎么办,就是一开始,让速度变慢,然后再正常请求的,经过思考,代码改造如下:
package main import "fmt"
import "time" func main() {
k := 0
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
limiter := time.Tick(time.Millisecond * 200)
slow := time.Tick(time.Millisecond * 400) for req := range requests {
if k < 3 {
<-slow
k++
}
<-limiter
fmt.Println("request", req, time.Now())
}
}
运行结果如下,可以看到,前三次间隔是400ms,第四次又还原回来间隔200ms:
request 1 2018-04-17 17:04:50.9986303 +0800 CST m=+0.405591505
request 2 2018-04-17 17:04:51.395919457 +0800 CST m=+0.802875205
request 3 2018-04-17 17:04:51.794626945 +0800 CST m=+1.201577217
request 4 2018-04-17 17:04:51.993709916 +0800 CST m=+1.400657453
request 5 2018-04-17 17:04:52.196450634 +0800 CST m=+1.603395386
我来解释下代码逻辑。为了实现需求,我在前面又设置了一个打点器,然后增加判断,如果k小于3,就从打点器中取值,然后k自增。这样的话保证了前三次取值慢,后面的取值快。
这时候有人会问了,那例子中是总共两个打点器,一个是400ms,一个是200ms,为什么前三次不是400+200总共600ms,而是间隔只有400ms呢?
我来解释一下,因为代码运行到<-slow时候是阻塞状态,通道内没有值,是需要打点器每隔400ms把值存入slow中,才能继续运行的。而<-limiter按理说也是阻塞状态,也需要打点器传值的。但是别忘了,limiter是200ms,在slow传值之前,limiter就已经存入值了。所以在if判断语句结束以后,limiter不用等待传值,直接取就行了。这样的话,在if条件执行完后,<-limiter执行是瞬间完成的,不用等待200ms的。
以上就是go语言中速率限制的一些思考和改造,在实际工作中,应该还有更加完美的解决方案,期待将来的改进。
005_针对于go语言中速率限制的思考的更多相关文章
- C语言中如何将二维数组作为函数的参数传递
今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...
- C语言中时钟编程
目录 C语言中时钟编程 1. 文章目的 2.基本概念 2.1 UTC时间 2.2 UNIX纪元时间 2.3 格林威治时间 (GMT) 3.时间转换 3.1 asctime函数 3.2 ctime函数 ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- python语言中的编码问题
在编程的过程当中,常常会遇到莫名其妙的乱码问题.很多人选择出了问题直接在网上找答案,把别人的例子照搬过来,这是快速解决问题的一个好办法.然而,作为一个严谨求实的开发者,如果不从源头上彻底理解乱码产生的 ...
- 在C语言中利用PCRE实现正则表达式
1. PCRE简介 2. 正则表达式定义 3. PCRE正则表达式的定义 4. PCRE的函数简介 5. 使用PCRE在C语言中实现正则表达式的解析 6. PCRE函数在C语言中的使用小例子 1. P ...
- C语言中函数声明实现的位置
在学习C语言的时候我遇到了这么个事情,因为之前先学习的C#,在C#编译器中,函数的声明位置不会影响编译的结果,但是在C语言中却发生了错误 先看一段代码: #include <stdio.h> ...
- C语言中的栈和堆
原文出处<http://blog.csdn.net/xiayufeng520/article/details/45956305#t0> 栈内存由编译器分配和释放,堆内存由程序分配和释放. ...
- 在易语言中调用MS SQL SERVER数据库存储过程方法总结
Microsoft SQL SERVER 数据库存储过程,根据其输入输出数据,笼统的可以分为以下几种情况或其组合:无输入,有一个或多个输入参数,无输出,直接返回(return)一个值,通过output ...
随机推荐
- JVM 学习笔记(四)
回顾: 在之前的文章中,我们主要体现了当堆内存设置的比较小的情况下,比如:-Xmx20M -Xms20M,在项目运行的过程中,不断往内存中去添加对象, 这时候就会出现OOM,也就是内存溢出,本文章将展 ...
- scrapy shell 的使用
是什么?:是一个终端下的调试工具,用来调试scrapy 安装ipython :pip install ipython 启动: scrapy shell + 需要请求的url 进来之后,response ...
- web 部署专题(四):压力测试(二)压力测试实例 flask 四种wsgi方式对比(tornado,Gunicorn,Twisted,Gevent)
使用工具:siege 代码结构: hello.py templates |--hello.html hello.py代码: from flask import Flask, render_templa ...
- 数据分析03 /基于pandas的数据清洗、级联、合并
数据分析03 /基于pandas的数据清洗.级联.合并 目录 数据分析03 /基于pandas的数据清洗.级联.合并 1. 处理丢失的数据 2. pandas处理空值操作 3. 数据清洗案例 4. 处 ...
- Android 性能优化 ---- 启动优化
Android 性能优化 ---- 启动优化 1.为什么要进行启动优化 一款应用的第一印象很重要,第一印象往往决定了用户的去留.打开一款应用,如果速度很快,很顺畅,那么很容易让人觉得这款应用背后的技术 ...
- TX 1核4G2M云服务器,376/2年,可免费续1年
腾讯云个人开发者活动 https://cloud.tencent.com/act/developer
- 据说比Spring快44倍的web开发框架,不妨试试
该框架称为:**light-4j **.官方网站简介:A fast, lightweight and more productive microservices framework.很简单,翻译过来就 ...
- try-catch- finally块中, finally块唯一不执行的情况是什么?
除非在try块或者catch块中调用了退出虚拟机的方法(即System.exit(1);),否则不管在try块.catch块中执行怎样的代码,出现怎样的情况,异常处理的finally块总是会被执行的 ...
- idea 自动生成try/catch代码块的快捷键
好像每个人的快捷键可能不同:我的是 Alt+Shift+Z 网上查的是 Ctrl+Alt+T 如果都不是可以点选工具栏生成try/catch(并可查看到自己的快捷键是什么):Code->Su ...
- blog only to u
2020/7/16 属于我的第一个博客正式上线,以后我将在此更新我的笔记和我的知识积累还有我那阔爱的小仙女!