ํฐ์คํ ๋ฆฌ ๋ทฐ
์ด ๊ธ์์๋
์ด ๊ธ์์๋ golang์ ํ์ฉํ rate limit์ ๋ํด์ ๋ค๋ฃน๋๋ค.
์ต๊ทผ์ ํ์ฌ ์
๋ฌด์์ tcp 100์ผ๋ก ๊ณ ์ ํ๊ณ ์ ์ ์ ๋ณด๋ฅผ ๋ฑ๋กํ๋ batch job์ ๊ฐ๋ฐํ์๋๋ฐ,
golang์์ ์ ๊ณตํ๋ rate limit ํจํค์ง๋ฅผ ํ์ฉํ์ต๋๋ค.
๊ทธ๋์ ๊ด๋ จํด์ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํด์!
์ด ๊ธ์ ์ฝ๋ ์ฌ๋๋ค์ ๋ค์๊ณผ ๊ฐ์ ์ง์์ ์ป์ด๊ฐ๊ธธ ๊ธฐ๋ํฉ๋๋ค
- ์ฒ๋ฆฌ์จ ์ ํ(rate limit)์ด๋?
- golang rate package
์ฃผ์*
์ ๊ฐ ๊ฒฝํํ ์ผ์ด์ค๋ ๋จ์ผ batch job์ kubernetes cronjob์ผ๋ก ๋์์ํจ ๊ฒฝ์ฐ์
๋๋ค.
๋ถ์ฐ ์์คํ
์์์ rate limiter๋ ๋ ๋ค๋ฅธ ๊ณ ๋ฏผ๊ฑฐ๋ฆฌ๋ค์ด ์กด์ฌํฉ๋๋ค.
๊ทธ ๊ณ ๋ฏผ๊ฑฐ๋ฆฌ์ ๋ํ ์ด์ผ๊ธฐ๋ ๊ธ ํ๋ฐ๋ถ์ ๋ค๋ฃน๋๋ค.
์ฒ๋ฆฌ์จ ์ ํ(rate limit)์ด๋?
rate limit์ ๋ง ๊ทธ๋๋ก ์ฌ์ฉ๋ ์ ์ด๋ฅผ ์๋ฏธํฉ๋๋ค. ๋คํธ์ํฌ ์์คํ
์์ ์ฒ๋ฆฌ์จ(rate)์ ์ ์ดํ๊ธฐ ์ํด ํ์ฉํด์.
์ด๋ ๊ฒ ๋งํ๋ฉด ์ดํดํ๊ธฐ ์ด๋ ค์ธ ์ ์์ผ๋ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ ์ฌ๋ก๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
- Dos(Denial of Service) ๊ณต๊ฒฉ์ ์ํ ์์ ๊ณ ๊ฐ(resource starvation) ๋ฐฉ์ง
- ๋น์ฉ ์ ๊ฐ
- third-part API ์ฌ์ฉ๋์ ๋ฐ๋ผ ๋น์ฉ์ ์ง๋ถํด์ผํ๋๊ฒฝ์ฐ ์ ์ฝ ๊ฐ๋ฅ
- ์๋ฒ ๊ณผ๋ถํ ๋ฐฉ์ง
- ๋ด์์ ์ค๋ ํธ๋ํฝ์ด๋ ์ฌ์ฉ์์ ์๋ชป๋ ์ด์ฉ ํจํธ์ผ๋ก ์ ๋ฐ๋ ํธ๋ํฝ์ ์ฐจ๋จ
- ์ธ๋ถ ์๋น์ค๋ก๋ถํฐ์ ํธ๋ํฝ ์ ์ด ์์ฒญ
- ํ๋ ฅ์ฌ) ์ ํฌ ์๋น์ค์ tps 100 ์ ๋๋ก ์์ฒญ์ ๋ณด๋ด์ฃผ์ธ์.
-> ์ค์ ๋ก ์ ๊ฐ ๊ฒช์๋ ์ํฉ์ด ์ด ์ผ์ด์ค!
- ํ๋ ฅ์ฌ) ์ ํฌ ์๋น์ค์ tps 100 ์ ๋๋ก ์์ฒญ์ ๋ณด๋ด์ฃผ์ธ์.
์ด ์ธ์๋ ๋ค์ํ ์ฌ๋ก๊ฐ ์์ ์ ์์ต๋๋ค.
์ฒ๋ฆฌ์จ ์ ํ ์๊ณ ๋ฆฌ์ฆ?
rate limit์ ๊ตฌํํ๋ ๋ฐ์๋ ๋ค์ํ ๋ฐฉ๋ฒ์ด ์๊ณ ๋ํ ์๋์ ๊ฐ์ด ๋ค์ํ ์ฒ๋ฆฌ์จ ์ ํ ์๊ณ ๋ฆฌ์ฆ์ด ์กด์ฌํฉ๋๋ค.
- ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ(token bucket)
- ๋์ถ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ(leaky bucket)
- ๊ณ ์ ์๋์ฐ ์นด์ดํฐ(fixed window counter)
- ์ด๋ ์๋์ฐ ๋ก๊ทธ(sliding window log)
- ์ด๋ ์๋์ฐ ์นด์ดํฐ(sliding window counter)
์ด ๊ธ์์๋ ์ ๋ง์ ์๊ณ ๋ฆฌ์ฆ ์ค ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ ์ผ์ด์ค๋ฅผ ๋ค๋ฃน๋๋ค!
ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ
ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ์ ์ด๋ฆ์์๋ ์ ์ ์๋ฏ์ด ํ ํฐ(token), ๋ฒํท(bucket) ์ด ๋๊ฐ์ง ์์๋ฅผ ํ์ฉํด ๊ตฌํํ๋ ์๊ณ ๋ฆฌ์ฆ์
๋๋ค.
ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ์ ํฐ ๋ฒ์์์์ ํ๋ก์ฐ๋ ์๋์ ๊ฐ์ด ๊ตฌ์ฑ๋ฉ๋๋ค
- ์ผ์ ์๊ฐ(r)๋ง๋ค ํ ํฐ์ด ์์ฑ๋๋ ๋ฒํท(๋ฐ๊ตฌ๋)์ด ์กด์ฌํ๊ณ
- ์์ฒญ์ด ์ฌ๋ ๋ฒํท์์ ํ ํฐ์ ํ๋ ๊บผ๋ด์ ์๋ชจํ๋ฉฐ (์ด ๋ฒํท์ ์ผ์ ์ฌ์ด์ฆ(b)๋ฅผ ๊ฐ์ง๋๋ค)
- ๋ฒํท์ ํ ํฐ์ด 0๊ฐ๊ฐ ๋๋ฉด ๊ฐ์ ธ๊ฐ ํ ํฐ์ด ์์ผ๋ฏ๋ก ์์ฒญ์ drop (์ดํ ํ ํฐ์ด ์ฑ์์ง ๋๊น์ง ๊ธฐ๋ค๋ ค์ผํจ)
ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํด rate limit์ ๊ตฌํํ๊ธฐ ์ํ ์ง์์ ๊ฐ๋ตํ๊ฒ ์์๋ดค์ผ๋ ์ด์ ์ค์ ์ฌ๋ก๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค
Golang rate package๋ฅผ ํ์ฉํ rate limit
์๋ ์ฝ๋๋ golang golang.org/x/time/rate ํจํค์ง๋ฅผ ํ์ฉํด ์ด๋น 100 ๊ฑด์ ์ฐ์ฐ์ ์ํํ๋๋ก rate limit์ ๊ตฌํํ ์ฝ๋์
๋๋ค.
์ง๊ธ์ ์ดํดํ๊ธฐ ์ด๋ ค์ธ ์ ์์ง๋ง ์๋ ์ฝ๋์์ ํ์ฉ๋ ์ง์๋ค์ ์ด ๊ธ์์ ์์๋ณด์ฃ !
package main
import (
"context"
"fmt"
"golang.org/x/time/rate"
"time"
)
func main() {
ctx := context.Background()
// rate limiter ์์ฑ
// r(rate tokens per seconds): 100
// b(bucket size): 100
rateLimiter := rate.NewLimiter(100, 100)
// ๋ฐ๋ณต ๋์ํ ๋์์ผ๋ก ๋จ์ํ๊ฒ size 1000์ ๋ฐฐ์ด ์์ฑ
values := make([]int64, 1000, 1000)
for i := range values {
values[i] = int64(1 + i)
}
now := time.Now()
for _, v := range values {
if err := rateLimiter.Wait(ctx); err != nil {
fmt.Println(err)
}
fmt.Println(v)
}
since := time.Since(now)
// 9.007893291s
fmt.Println(since)
}
golang.org/x/time/rate ํจํค์ง
golang.org/x/time/rate ํจํค์ง์์๋ rate limit์ ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๊ตฌํํ๊ณ ์์ต๋๋ค.
https://pkg.go.dev/golang.org/x/time/rate
์ค์ ๋ก ์์ชฝ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฌ ๋ค์ด๊ฐ๋ฉด wait()ํจ์ ์์ ์๋์ ๊ฐ์ด ๊ตฌ์ฑ๋์ด ์๋ ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
๋ถ์ฐ ์์คํ ์์์ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น?
๋ถ์ฐ ์์คํ
์์ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น๋ ๋ ๋ค๋ฅธ ๊ณ ๋ฏผ์ด ํ์ํฉ๋๋ค. ๋ถ์ฐ ์์คํ
ํ๋ฉด ๋ ์ค๋ฅด๋ ๋ํ์ ์ธ ๋์์ฑ ๋ฌธ์ ๋ค์ ํด๊ฒฐํด์ผํ์ฃ .
๋ํ์ ์ธ ๊ณ ๋ฏผ๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๊ฒฝ์ ์กฐ๊ฑด(race condition)
- DB์์๋ ๋ง์ฐฌ๊ฐ์ง์ง๋ง ์ฌ๋ฌ ์์ฒญ์ด ๋ค์ด์ค๋ ์ํฉ์์ ๊ฒฝ์ ์กฐ๊ฑด์ ํญ์ ๊ณ ๋ฏผ์
๋๋ค.
๊ฒฝ์ ์กฐ๊ฑด์ lock, Lua script ๊ทธ๋ฆฌ๊ณ redis์ sorted set์ ํ์ฉํด์ ํด๊ฒฐํด๋ณผ ์ ์์ต๋๋ค. - redis๋ single thread๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ ๋ณด๋ค ์ฝ๊ฒ ํ์ฉํด๋ณผ ์ ์์ต๋๋ค.
- lock์ ๊ฒฐ ๊ฒฝ์ฐ ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ๋์ด๋๋ ๋ถ์์ฉ๋ ์์ต๋๋ค.
- ๋ฌผ๋ก ๋น์ฉ์ ์ ์ ํ๊ฒ ๊ณ ๋ฏผํด์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ํํ๋ ๊ฒ๋ ์ค์ํฉ๋๋ค.
- DB์์๋ ๋ง์ฐฌ๊ฐ์ง์ง๋ง ์ฌ๋ฌ ์์ฒญ์ด ๋ค์ด์ค๋ ์ํฉ์์ ๊ฒฝ์ ์กฐ๊ฑด์ ํญ์ ๊ณ ๋ฏผ์
๋๋ค.
- ๋๊ธฐํ ์ด์
- ํธ๋ํฝ์ด ๋์ด๋๋ฉด ํ ๋์ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น ์๋ฒ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์ต๋๋ค.
์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น๋ ์ค์ผ์ผ๋งํด์ผํ๋ ์์ ์ด ์ค๋ฉด ๊ฐ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น ๊ฐ์ ๋๊ธฐํ ๋ฌธ์ ๋ ๊ณ ๋ฏผํด์ผํฉ๋๋ค. - ์ด ๊ฒฝ์ฐ sticky sessionํน์ redis์ ๊ฐ์ ๋ณ๋์ ์์์ฑ layer๋ฅผ ํ์ฉํด๋ณผ ์ ์์ต๋๋ค. redis cluster์ ์์ํ ์๋ ์์ฃ
- ํธ๋ํฝ์ด ๋์ด๋๋ฉด ํ ๋์ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น ์๋ฒ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์ต๋๋ค.
๊ฒฐ๊ตญ ํธ๋ ์ด๋์คํ
๊ฒฐ๊ตญ์ ๋ชจ๋ ๊ธฐ์ ์ ํ์ ๊ฐ ์ํฉ์ ๋ง๊ฒ ํธ๋ ์ด๋์คํ๋ฅผ ์ ๊ณ ๋ คํด์ผํฉ๋๋ค.
์ ์ ๊ฒฝ์ฐ์๋ ํ๋์ ๋ฐฐ์น์ก ํ์ดํ๋ผ์ธ์์ ๋ก์ง์ ๋์์์ผฐ๊ธฐ ๋๋ฌธ์ ๊ฐ๋จํ๊ฒ application level์์ rate limit์ ํ์ฉํด๋ณผ ์ ์์์ต๋๋ค.
์ฌ๋ฌ๋ถ๋ค์ ์ฌ๋ก์์๋ ์ด๋ค ์ธํ๋ผ๋ฅผ ํ์ฉํ๋์? ์ ๋ง rate limit์ด ํ์ํ ์๊ตฌ์ฌํญ์ธ๊ฐ์? ๋ค๋ฅด๊ฒ ํธ๋ ๋ฐฉ๋ฒ์ ์์๊น์?
๋ฐ๋ผ๋ณด๋ ์๊ฐ์ ์ ํํ์ฌ ์ด๋ ค์ด ๋ฌธ์ ๋ฅผ ๊ฐ๋จํ ๋ฌธ์ ๋ก ์นํํ๊ฑฐ๋ ์์ ๋ฌธ์ ๋ก ๋๋ ์ ๊ฐ๋จํ๊ฒ ํ์ด๋ด๋ ๊ฒ๋ ์์ง๋์ด์ ์ค์ํ ์ญ๋์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์ถ๊ฐ๋ก https://github.com/uber-go/ratelimit ๋ผ๋ ์ฐ๋ฒ์์ rate limit์ ์ํด ๋ง๋ ํจํค์ง๋ ์กด์ฌํฉ๋๋ค.
์ด ํจํค์ง๋ ๊ฐ๋จํ API์ ๋น๊ต์ ์ ์ ์ค๋ฒํค๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ค๋ ์๊ฐํ rate ํจํค์ง๋ ์ข ๋ ๋ํ
์ผํ๊ฒ ์ค์ ํ ์ ์๊ณ ๋ฐ๋๋ก ๊ฐ๋จํ ์๊ตฌ์ฌํญ์ด๋ผ๋ฉด ํด๋น ํจํค์ง๋ฅผ ํ์ฉํด๋ด๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค!
Action item
์ฐ๋ฆฌ ๋ชจ๋ ํญ์ ํธ๋ ์ด๋์คํ๋ฅผ ์ ๊ณ ๋ คํด์ ํ์ค์ ์ผ๋ก ์ ํํ๋ ์์ง๋์ด๋ง์ ํ๊ธฐ ์ํด ๊นจ์ด์์ผ๋ ค ๋ ธ๋ ฅํ๊ธฐ
'Go' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Go : ๊ณ ๋ฃจํด(goroutine), ์ฑ๋(channels) (0) | 2022.03.20 |
---|---|
Go : struct, type, method (0) | 2022.03.20 |
Go ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ ๋ํด์ ์์๋ณด์ (0) | 2022.03.18 |
- Total
- Today
- Yesterday
- ์คํ/ํ
- ์ข์ ๊ฐ๋ฐ์
- ์ถ์ ์ง๋
- AWS re:Invent 2023
- Aws Reinvent 2023
- HTTP
- grpc client
- mysql
- ํ(Heap)
- ๋ฑ ํฌ์๋ฌ๋ ๊ฐ๋ฐ์
- 2๋ ์ฐจ ์๋ฒ ๊ฐ๋ฐ์
- ์ข์ ์ฝ๋๋ ๋ฌด์์ธ๊ฐ?
- ์ข์ ์์ง๋์ด
- ์ข์ ๊ฐ๋ฐ์ ๋๊ธฐ
- ํ๋ก๊ทธ๋๋จธ์ค
- Go
- Golang
- 2023 ํ๊ณ
- ์๊ณ ๋ฆฌ์ฆ
- ์ฝ๋ฉํ ์คํธ
- ๊น์ด/๋๋น ์ฐ์ ํ์(DFS/BFS)
- ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค
- ํด์
- mysql ์คํ ๊ณํ
- ์ฅ์ ํ๊ณ
- rate limit
- kotlin s3 upload
- 2023 ๊ฐ๋ฐ์ ํ๊ณ
- golang oomkilled
- ๋ฐฑ์ค
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |