|
Rate limiting ou limitador de frequência é um mecanismo importante para controlar a utilização de recursos e manter a qualidade do serviço. Go suporta o rate limiting com goroutines, canais e tickers de maneira bem elegante. |
|
![]()
package main |
|
import ( "fmt" "time" ) |
|
func main() { |
|
|
Primeiro será apresentado rate limiting básico.
Suponha que seja necessário limitar o tratamento
das requisições recebidas, que serão servidas em
um canal |
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
|
|
Este canal limitador, ou |
limiter := time.Tick(200 * time.Millisecond)
|
|
Ao bloquear um recebimento do canal limitador antes de atender a cada solicitação, será tratada 1 solicitação por vez, a cada 200 milissegundos. |
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
}
|
|
Também é possível permitir envio de lotes de pequena
quantidade ou |
burstyLimiter := make(chan time.Time, 3)
|
|
Preenchendo o canal com requisições para representar os lotes, ou bursting. |
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
|
|
A cada 200 milisegundos, será adicionado um valor
ao canal |
go func() {
for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t
}
}()
|
|
Agora é simulado outras 5 requisições sendo recebidas. As 3 primeiras serão beneficiadas pela capacidade do |
//`burstyLimiter`de aceitar requisições em lote .
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())
}
}
|
|
Ao executar o código é fácil de visualizar o primeiro envio de requisições tratadas uma vez a cada ~200 milisegundos, como esperado. |
$ go run rate-limiting.go request 1 2012-10-19 00:38:18.687438 +0000 UTC request 2 2012-10-19 00:38:18.887471 +0000 UTC request 3 2012-10-19 00:38:19.087238 +0000 UTC request 4 2012-10-19 00:38:19.287338 +0000 UTC request 5 2012-10-19 00:38:19.487331 +0000 UTC |
|
Para o segundo conjunto de requisições, são tratadas de imediato as 3 primeiras, por conta do limitador em lotes e, só então as 2 remanescentes com intervalo de ~200 milisegundos entre cada uma. |
request 1 2012-10-19 00:38:20.487578 +0000 UTC request 2 2012-10-19 00:38:20.487645 +0000 UTC request 3 2012-10-19 00:38:20.487676 +0000 UTC request 4 2012-10-19 00:38:20.687483 +0000 UTC request 5 2012-10-19 00:38:20.887542 +0000 UTC |
Próximo exemplo: Atomic Counters.