Реализация ограничения скорости в Go

GolangGolangBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном задании показано, как реализовать ограничение скорости в Go с использованием горутин, каналов и тикеров.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/ConcurrencyGroup(["Concurrency"]) go/ConcurrencyGroup -.-> go/rate_limiting("Rate Limiting") subgraph Lab Skills go/rate_limiting -.-> lab-15498{{"Реализация ограничения скорости в Go"}} end

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

Задача заключается в том, чтобы ограничить обработку входящих запросов для поддержания качества обслуживания и контроля за использованием ресурсов.

  • Язык программирования 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 с использованием горутин, каналов и тикеров для контроля использования ресурсов и поддержания качества обслуживания.