Введение
В этом лабораторном задании показано, как реализовать ограничение скорости в Go с использованием горутин, каналов и тикеров.
This tutorial is from open-source community. Access the source code
💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал
В этом лабораторном задании показано, как реализовать ограничение скорости в Go с использованием горутин, каналов и тикеров.
Задача заключается в том, чтобы ограничить обработку входящих запросов для поддержания качества обслуживания и контроля за использованием ресурсов.
## Запустив нашу программу, мы видим, что первая партия запросов
## обрабатывается раз в ~200 миллисекунд, как и ожидалось.
$ 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
## Для второй партии запросов мы сразу обрабатываем первые
## 3, благодаря ограничению скорости с возможностью всплеска,
## а затем обрабатываем оставшиеся 2 с задержками в ~200 мс каждые.
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
Ниже представлен полный код:
// [_Ограничение скорости_](https://en.wikipedia.org/wiki/Rate_limiting)
// - важный механизм для контроля использования ресурсов
// и поддержания качества обслуживания. Go элегантно
// поддерживает ограничение скорости с использованием
// горутин, каналов и [тикеров](tickers).
package main
import (
"fmt"
"time"
)
func main() {
// Сначала рассмотрим базовое ограничение скорости. Предположим,
// что мы хотим ограничить обработку входящих запросов.
// Мы будем обрабатывать эти запросы из канала с тем же именем.
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
// Канал `limiter` будет получать значение каждые 200 миллисекунд.
// Это регулятор в нашей схеме ограничения скорости.
limiter := time.Tick(200 * time.Millisecond)
// Блокируя прием из канала `limiter` перед обработкой каждого запроса,
// мы ограничиваем себя обработкой 1 запроса каждые 200 миллисекунд.
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
}
// Возможно, мы хотим позволить короткие всплески запросов в нашей
// схеме ограничения скорости, сохраняя при этом общий лимит скорости.
// Мы можем это сделать, буферизируя наш канал `limiter`.
// Канал `burstyLimiter` позволит всплески до 3 событий.
burstyLimiter := make(chan time.Time, 3)
// Заполним канал, чтобы представить допустимый всплеск.
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
// Каждые 200 миллисекунд мы попытаемся добавить новое значение в
// `burstyLimiter`, до его лимита в 3.
go func() {
for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t
}
}()
// Теперь имитируем 5 более входящих запросов. первые 3 из них
// будут получать выгоду от возможностей всплеска `burstyLimiter`.
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())
}
}
В этом лабораторном задании показано, как реализовать ограничение скорости в Go с использованием горутин, каналов и тикеров для контроля использования ресурсов и поддержания качества обслуживания.