Go 에서 속도 제한 구현하기

Beginner

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

소개

이 랩은 Go 에서 고루틴 (goroutine), 채널 (channel) 및 티커 (ticker) 를 사용하여 속도 제한 (rate limiting) 을 구현하는 방법을 보여줍니다.

속도 제한 (Rate Limiting)

문제는 서비스 품질을 유지하고 리소스 사용률을 제어하기 위해 들어오는 요청 처리를 제한하는 것입니다.

  • Go 프로그래밍 언어
  • 고루틴 (goroutine), 채널 (channel) 및 티커 (ticker) 에 대한 기본적인 이해
## 프로그램을 실행하면 원하는 대로 첫 번째 요청 배치가
## 약 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 개는 각각 약 200ms 지연으로 처리합니다.
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 는
// 고루틴 (goroutine), 채널 (channel) 및 [티커 (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` 채널에서 수신을 차단하여
    // 200 밀리초마다 1 개의 요청으로 제한합니다.
    for req := range requests {
        <-limiter
        fmt.Println("request", req, time.Now())
    }

    // 전체 속도 제한을 유지하면서 속도 제한 체계에서
    // 짧은 요청 버스트를 허용할 수 있습니다.
    // 채널을 버퍼링하여 이를 수행할 수 있습니다. 이 `burstyLimiter`
    // 채널은 최대 3 개의 이벤트를 버스트할 수 있습니다.
    burstyLimiter := make(chan time.Time, 3)

    // 허용된 버스팅을 나타내기 위해 채널을 채웁니다.
    for i := 0; i < 3; i++ {
        burstyLimiter <- time.Now()
    }

    // 200 밀리초마다 최대 3 개까지 `burstyLimiter` 에
    // 새 값을 추가하려고 시도합니다.
    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 에서 고루틴 (goroutine), 채널 (channel) 및 티커 (ticker) 를 사용하여 리소스 사용률을 제어하고 서비스 품질을 유지하기 위해 속도 제한 (rate limiting) 을 구현하는 방법을 보여줍니다.