ограничение скорости

This commit is contained in:
badkaktus 2019-10-08 16:21:55 +03:00
parent 50383b5cab
commit acb7585e84
3 changed files with 34 additions and 32 deletions

View File

@ -33,7 +33,7 @@ Select
Тикеры (повторения) (Tickers) Тикеры (повторения) (Tickers)
Пулы воркеров (Worker Pools) Пулы воркеров (Worker Pools)
WaitGroups WaitGroups
Rate Limiting Ограничение скорости (Rate Limiting)
Atomic Counters Atomic Counters
Mutexes Mutexes
Stateful Goroutines Stateful Goroutines

View File

@ -1,8 +1,7 @@
// <em>[Rate limiting](http://en.wikipedia.org/wiki/Rate_limiting)</em> // <em>[Ограничение скорости](http://en.wikipedia.org/wiki/Rate_limiting)</em>
// is an important mechanism for controlling resource // является важным механизмом контроля использования ресурсов и
// utilization and maintaining quality of service. Go // поддержания качества обслуживания. Go элегантно поддерживает
// elegantly supports rate limiting with goroutines, // ограничение скорости с помощью горутин, каналов и [тикеров](tickers).
// channels, and [tickers](tickers).
package main package main
@ -13,52 +12,54 @@ import (
func main() { func main() {
// First we'll look at basic rate limiting. Suppose // Сначала мы рассмотрим базовое ограничение скорости.
// we want to limit our handling of incoming requests. // Предположим, мы хотим ограничить нашу обработку
// We'll serve these requests off a channel of the // входящих запросов. Мы будем обслуживать эти запросы
// same name. // с одноименного канала.
requests := make(chan int, 5) requests := make(chan int, 5)
for i := 1; i <= 5; i++ { for i := 1; i <= 5; i++ {
requests <- i requests <- i
} }
close(requests) close(requests)
// This `limiter` channel will receive a value // Канал `limiter` будет получать значение каждые
// every 200 milliseconds. This is the regulator in // 200мс. Это то, что регулирует скорость в нашей
// our rate limiting scheme. // схеме.
limiter := time.Tick(200 * time.Millisecond) limiter := time.Tick(200 * time.Millisecond)
// By blocking on a receive from the `limiter` channel // Блокируя прием от канала `limiter` перед
// before serving each request, we limit ourselves to // обслуживанием каждого запроса, мы ограничиваем себя
// 1 request every 200 milliseconds. // одним запросом каждые 200 миллисекунд.
for req := range requests { for req := range requests {
<-limiter <-limiter
fmt.Println("request", req, time.Now()) fmt.Println("request", req, time.Now())
} }
// We may want to allow short bursts of requests in // Мы можем разрешить короткие всплески запросов в
// our rate limiting scheme while preserving the // нашей схеме ограничения скорости при сохранении
// overall rate limit. We can accomplish this by // общего ограничения скорости. Мы можем сделать это
// buffering our limiter channel. This `burstyLimiter` // путем буферизации нашего канала ограничения. Этот
// channel will allow bursts of up to 3 events. // канал `burstyLimiter` будет позволять делать до
// 3 событий.
burstyLimiter := make(chan time.Time, 3) burstyLimiter := make(chan time.Time, 3)
// Fill up the channel to represent allowed bursting. // Заполняем канал, чтобы предоставить возможность
// ускорить.
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
burstyLimiter <- time.Now() burstyLimiter <- time.Now()
} }
// Every 200 milliseconds we'll try to add a new // Каждые 200мс мы будем пытаться добавлять новое
// value to `burstyLimiter`, up to its limit of 3. // значение в `burstyLimiter`, до своего предела
// в 3 значения.
go func() { go func() {
for t := range time.Tick(200 * time.Millisecond) { for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t burstyLimiter <- t
} }
}() }()
// Now simulate 5 more incoming requests. The first // Теперь смоделируем еще 5 входящих запросов. Первые
// 3 of these will benefit from the burst capability // 3 из них получат выгоду от вместимости `burstyLimiter`.
// of `burstyLimiter`.
burstyRequests := make(chan int, 5) burstyRequests := make(chan int, 5)
for i := 1; i <= 5; i++ { for i := 1; i <= 5; i++ {
burstyRequests <- i burstyRequests <- i

View File

@ -1,5 +1,5 @@
# Running our program we see the first batch of requests # При запуске нашей программы мы видим, что первая
# handled once every ~200 milliseconds as desired. # партия запросов обрабатывается каждые ~200мс.
$ go run rate-limiting.go $ go run rate-limiting.go
request 1 2012-10-19 00:38:18.687438 +0000 UTC request 1 2012-10-19 00:38:18.687438 +0000 UTC
request 2 2012-10-19 00:38:18.887471 +0000 UTC request 2 2012-10-19 00:38:18.887471 +0000 UTC
@ -7,9 +7,10 @@ request 3 2012-10-19 00:38:19.087238 +0000 UTC
request 4 2012-10-19 00:38:19.287338 +0000 UTC request 4 2012-10-19 00:38:19.287338 +0000 UTC
request 5 2012-10-19 00:38:19.487331 +0000 UTC request 5 2012-10-19 00:38:19.487331 +0000 UTC
# For the second batch of requests we serve the first # Для второго пула запросов мы обслуживаем первые
# 3 immediately because of the burstable rate limiting, # 3 сразу из-за использования ограничения скорости,
# then serve the remaining 2 with ~200ms delays each. # затем обслуживаем оставшиеся 2 с задержками ~200мс
# каждый.
request 1 2012-10-19 00:38:20.487578 +0000 UTC request 1 2012-10-19 00:38:20.487578 +0000 UTC
request 2 2012-10-19 00:38:20.487645 +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 3 2012-10-19 00:38:20.487676 +0000 UTC