我通过工人通道接收到大约20万条消息/秒,我需要将发送给客户端的消息数限制为每秒仅20条。 每50毫秒发送1条消息
在LOOP的帮助下,工作人员将在程序的整个生命周期中仍然活着(并且不会为每个消息打开一个通道)。
我的目标: -由于消息的顺序很重要,因此我想跳过在阻塞的50毫秒内出现的所有消息,只保存最新的消息 -如果最新消息是在阻塞的50毫秒之内到来的,我希望当阻塞时间在循环内结束且没有新消息到来时处理已保存的消息! <-这是我的问题
我的策略 -继续将尚未处理的最新消息发送到同一频道
但是问题在于,如果该消息是在(来自应用程序的)新消息发出之后发送的,该怎么办?
下面的代码更像是一个工作代码,只是想知道如何做的秘诀/方法。
func example (new_message_from_channel <-chan *message) {
default = message
time = now_milliseconds
diff_accepted = 50milli
for this_message := range new_message_from_channel {
if now_millisecond - time >= diff_accepted {
send_it_to_the_client
time = now_milliseconds
} else {
//save the latest message
default = this_message
//My problem is how to process this latest message when the blocked 50ms is over and no new message coming ?!
//My strategy - keep sending it to the same channel
theChannel <- default
}
}
}
如果您有一个优雅的方法,欢迎与我分享:)
答案 0 :(得分:0)
使用速率限制器,您可以创建一个throttle
函数,该函数将采用:速率和通道作为输入;然后返回两个渠道-一个渠道包括所有原始渠道项目,另一个渠道仅以固定的速率中继项目:
func throttle(r time.Duration, in <-chan event) (C, tC <-chan event) {
// "writeable" channels
var (
wC = make(chan event)
wtC = make(chan event)
)
// read-only channels - returned to caller
C = wC
tC = wtC
go func() {
defer close(wC)
defer close(wtC)
rl := rate.NewLimiter(
rate.Every(r),
1,
)
// relays input channel's items to two channels:
// (1) gets all writes from original channel
// (2) only writes at a fixed frequency
for ev := range in {
wC <- ev
if rl.Allow() {
wtC <- ev
}
}
}()
return
}
工作示例:https://play.golang.org/p/upei0TiyzNr
编辑:
为避免使用速率限制器,而应使用简单的time.Ticker
:
tick := time.NewTicker(r)
for ev := range in {
select {
case wC <- ev: // write to main
case <-tick.C:
wC <- ev // write to main ...
wtC <- ev // ... plus throttle channel
}
}