• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Explorando o pacote Rate e o algoritmo de Token Bucket

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
No post sobre

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

citei que atualmente é comum que a sua aplicação tenha que se comunicar com outras e, com isso, estratégias de controle de tráfego se tornam essenciais. Recentemente descobri o

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

uma estratégia baseada em tokens para controlar o tráfego.

Imagine que você tenha 5 ingressos para um brinquedo e que a cada hora você ganhe um novo ingresso, mas nunca podendo exceder o limite de 5. A cada ida ao brinquedo, um ticket é usado. Dessa forma, ao utilizar todos os seus tickets, você não pode ir ao brinquedo até ganhar um novo ticket. É um algoritmo bem interessante, utilizado, por exemplo, pelo PIX, para controlar a busca de chaves e evitando que um malfeitor pegue dados de usuários.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Traduzindo para código, vamos propor um cenário em que 10 goroutines sejam inicializadas e vão executar uma ação qualquer. Caso você ainda não conheça sobre

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

recomendo o meu post sobre o tema.


package main

import "golang.org/x/time/rate"

func main() {
c := make(chan int)

for range 10 {
go doSomething(i, c)
}

for range 10 {
<-c
}
}

func doSomething(x int, c chan int) {
fmt.Printf("goroutine %d did something\n", x)

c <- x
}

Ao executar o código acima, pode-se notar que as goroutines foram executadas sem nenhum controle maior.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



O algoritmo de Token Bucket vem da necessidade de controlar essa execução e, como sempre, a própria linguagem e/ou a comunidade Go nos fornecem uma solução, neste caso o pacote

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

Seu uso é bem simples, primeiro é necessário inicializar um novo Limitter, que recebe a quantidade máxima de tokens disponível e um Limit, que define a taxa com que novos tokens são gerados por segundo.


package main

import "golang.org/x/time/rate"

func main() {
c := make(chan int)
r := rate.Limit(1.0) // refreshes 1 token per second
l := rate.NewLimiter(r, 5) // allows 5 tokens max

... // do more stuff
}

O legal do pacote rate é que ele possui três estratégias diferentes. A primeira delas é a estratégia de allow.


func doSomethingWithAllow(l *rate.Limiter, x int, c chan int) {
if l.Allow() {
fmt.Printf("Allowing %d to run\n", x)
}

c <- x
}

Nesta estratégia, a execução será permitida se existir um token para ser consumido naquele momento e, caso não exista, nada será executado.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



A segunda estratégia é chamada de wait e é provavelmente a estratégia mais comum de ser utilizada, segundo o autor do pacote.


func doSomethingWithWait(ctx context.Context, l *rate.Limiter, x int, c chan int) {
err := l.Wait(ctx)
if err != nil {
fmt.Printf("Error waiting for %d: %v\n", x, err)
c <- x
return
}

fmt.Printf("Allowing %d to run\n", x)
c <- x
}

Nesta estratégia, a goroutine vai esperar até existir um token disponível para ser usado.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Por fim, temos a estratégia de reserve. Como o nome diz, você reserva o próximo ticket disponível e aguarda até o momento dele ser emitido.


func doSomethingWithReserve(l *rate.Limiter, x int, c chan int) {
r := l.Reserve()
if !r.OK() {
return
}

fmt.Printf("Reserving %d to run\n", x)
d := r.Delay()
time.Sleep(d)
fmt.Printf("Allowing %d to run\n", x)

c <- x
}

Esta estratégia é bem parecida com a de wait, contudo nos permite controlar com mais detalhes e saber quando é possível executar novamente.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Além disso, todas essas estratégias permitem você queimar mais de um ticket, caso seja necessário. Por exemplo, a função Allow() vira AllowN(t time.Time, n int), onde t é o tempo para acontecer n eventos.

Outra funcionalidade que achei bem legal, foi a possiblidade de se fazer um Circuit Breaker simples utilizando esse pacote e o tipo Sometimes. Nele é possível configurar os seguintes parâmetros:

  • First: as primeiras N chamadas serão executadas.
  • Every: A cada N chamadas executadas, uma será bloqueada.
  • Inverval: o limite de chamadas no tempo.

package main

import (
"fmt"

"golang.org/x/time/rate"
)

func main() {
s := rate.Sometimes{Every: 2}

for i := range 10 {
s.Do(func() { fmt.Printf("Allowing %d to run!\n", i) })
}
}

Como podemos ver, a cada duas chamadas, uma é bloqueada.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Conclusão


O token bucket é um algoritmo de controle de tráfego extremamente interessante, já que ele permite barrar execuções excedentes e agendar execuções futuras. A implementação em Go é simples de se utilizar, além de ser segura ao se utilizar em múltiplas goroutines.

O pacote rate ainda provê uma simples implementação de circuit breaker, evitando assim a adição de mais bibliotecas de terceiros em seu código, caso você deseje utilizar ambos os métodos em sua aplicação.

Contudo, vale a pena citar que o pacote ainda é experimental, podendo mudar o contrato entre as versões, ser descontinuado ou até mesmo incorporado a stdlib.

Para ver todos os exemplos, acesse este

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Links úteis



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу