การดู : 0

12/04/2026 18:16น.

JS2GO EP.43 การทำ Rate Limiting และ Throttling ใน Go และ Node.js

JS2GO EP.43 การทำ Rate Limiting และ Throttling ใน Go และ Node.js

#Token Bucket

#Throttling

#Go

#Node.js

#Rate Limiting

ควบคุมโหลด ป้องกัน DDoS และทำให้ API “เสถียรแม้ถูกยิงหลายหมื่น request/วินาที” 🚀

 

Rate Limiting คือเทคนิคที่บอกระบบว่า 👉 “ผู้ใช้ 1 ราย สามารถส่ง request ได้กี่ครั้งภายในช่วงเวลาเท่าไหร่” เพื่อป้องกันไม่ให้ระบบถูกยิงเกินกำลังที่รองรับได้

 

ใช้สำหรับแก้ปัญหาเหล่านี้:

  • API ล่มเพราะถูกยิง request ถี่เกินไป
  • Hacker brute-force login
  • Bot spam / script อันตราย
  • บริการหลังบ้าน เช่น DB/Cache overload
  • ค่าเซิร์ฟเวอร์พุ่งไม่จำเป็น
  • ระบบต้องรักษาคุณภาพของบริการ (QoS)

 

ใน EP นี้… คุณจะได้เข้าใจ Pattern ของ Rate Limiting แบบ Production Ready ทั้งใน Go และ Node.js พร้อมโค้ดที่แทบจะนำไปใช้จริงได้ทันที ✔

 

⭐ 1) ทำไม “Rate Limiting” จำเป็นในระบบระดับ Production?

 

ถ้าไม่มี Rate Limit → ระบบจะพังแน่นอน เพราะ:

ปัญหาผลกระทบ
User ส่ง request ผิดพลาดเป็นหมื่นครั้ง (infinite loop)API ค้างทั้งระบบ
Bot ยิงถี่CPU 100%
Hacker brute-force passwordSecurity breach
API gateway overloadLatency พุ่ง
DB ถูกคิวตันQuery fail ทั้งระบบ
ระบบ microservices call กันเองแบบไม่มี limitเกิด cascade failure

 

Rate Limiting = Safety Shield ของ API ในทุกระบบจริง 🔰

 

⭐ 2) 3 Approaches ที่ใช้จริงใน Production

 

🔶 Token Bucket (นิยมที่สุด)

แนวคิด:

  • Bucket ใส่ token ได้จำนวนหนึ่ง
  • มีการเติม token ตามเวลา
  • ทุก request ต้องใช้ 1 token
  • ถ้า token หมด → block หรือ delay

 

เหมาะกับ:

  • ระบบที่มี burst traffic
  • Public API
  • Microservices

 

ข้อดี

✔ รองรับการยิงทีละเยอะ (burst) ได้
✔ ง่ายต่อการ implement
✔ ใช้ได้ทั้งในระบบ local และ distributed

 

🔶 Leaky Bucket

แนวคิด:

  • งานถูกเทเข้าบัคเก็ตได้ไม่จำกัด
  • แต่ “ไหลออก” ด้วยอัตราคงที่
    เหมือนการควบคุม throughput ให้คงที่มากที่สุด

 

เหมาะกับ:

  • Streaming
  • Log processing
  • Job queue

 

ข้อดี

✔ Traffic stable
✔ Load หลังบ้านนิ่ง

 

🔶 Sliding Window

แนวคิด:

นับจำนวน request ภายในช่วง “เวลาเลื่อน” เช่น 1 นาทีล่าสุด

 

เหมาะกับ:

  • Login/Authentication
  • API ที่ต้องป้องกัน brute-force
  • Public API ที่ต้องการความแม่นยำสูง

 

ข้อดี

✔ แม่นยำกว่า Fixed Window
✔ ป้องกัน request spike ได้ดีกว่า

 

⭐ 3) ตัวอย่างโค้ด Production Go (Golang)

 

🟦 Token Bucket — Go (Middleware Version)

 

package main

import (
	"net/http"
	"sync"
	"time"
)

type TokenBucket struct {
	tokens     float64
	capacity   float64
	fillRate   float64 // token per second
	lastFilled time.Time
	mu         sync.Mutex
}

func NewTokenBucket(capacity, fillRate float64) *TokenBucket {
	return &TokenBucket{
		tokens:     capacity,
		capacity:   capacity,
		fillRate:   fillRate,
		lastFilled: time.Now(),
	}
}

func (tb *TokenBucket) Allow() bool {
	tb.mu.Lock()
	defer tb.mu.Unlock()

	now := time.Now()
	elapsed := now.Sub(tb.lastFilled).Seconds()
	tb.tokens = tb.tokens + elapsed*tb.fillRate

	if tb.tokens > tb.capacity {
		tb.tokens = tb.capacity
	}

	tb.lastFilled = now

	if tb.tokens >= 1 {
		tb.tokens -= 1
		return true
	}
	return false
}

func RateLimit(tb *TokenBucket) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if !tb.Allow() {
				http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}

func main() {
	tb := NewTokenBucket(10, 5) // capacity=10, fillRate=5 tokens/s

	mux := http.NewServeMux()
	mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})

	http.ListenAndServe(":8080", RateLimit(tb)(mux))
}

 

🟦 Sliding Window — Go

 

var (
	requests = make(map[string][]time.Time)
	mu       sync.Mutex
	limit    = 5
	window   = 10 * time.Second
)

func SlidingWindow(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ip := r.RemoteAddr
		now := time.Now()

		mu.Lock()
		history := requests[ip]

		// keep only valid timestamps
		valid := history[:0]
		for _, t := range history {
			if now.Sub(t) <= window {
				valid = append(valid, t)
			}
		}

		if len(valid) >= limit {
			mu.Unlock()
			http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
			return
		}

		requests[ip] = append(valid, now)
		mu.Unlock()

		next.ServeHTTP(w, r)
	})
}

 

⭐ 4) ตัวอย่างโค้ด Production Node.js (Express)

 

🟧 Token Bucket — Node.js

 

class TokenBucket {
  constructor(capacity, fillRate) {
    this.capacity = capacity;
    this.tokens = capacity;
    this.fillRate = fillRate;
    this.lastRefill = Date.now();
  }

  allow() {
    const now = Date.now();
    const elapsed = (now - this.lastRefill) / 1000;

    this.tokens = Math.min(
      this.capacity,
      this.tokens + elapsed * this.fillRate
    );

    this.lastRefill = now;

    if (this.tokens >= 1) {
      this.tokens -= 1;
      return true;
    }
    return false;
  }
}

function rateLimit(bucket) {
  return (req, res, next) => {
    if (!bucket.allow()) {
      return res.status(429).send("Too Many Requests");
    }
    next();
  };
}

 

🟧 Sliding Window — Node.js

 

const windowMs = 10 * 1000;
const limit = 5;
const history = new Map();

function slidingWindow(req, res, next) {
  const ip = req.ip;
  const now = Date.now();

  const reqLog = history.get(ip) || [];
  const filtered = reqLog.filter(t => now - t <= windowMs);

  if (filtered.length >= limit) {
    return res.status(429).send("Too Many Requests");
  }

  filtered.push(now);
  history.set(ip, filtered);

  next();
}

 

⭐ 5) Production Tips (สำคัญมาก)

 

✔ ใช้ Redis สำหรับระบบ multi-instance (ถ้าคุณมีหลาย container/pod → memory local จะไม่ sync)

✔ ทำ rate limit หลายชั้น

  • API Gateway
  • Load Balancer
  • App server

✔ Sliding Window เหมาะกับ Public API
✔ Token Bucket เหมาะกับ Microservices
✔ ใช้ exponential backoff สำหรับ retry

✔ ตั้ง Log + Monitoring ให้ครบ
เพื่อดูว่า rate limit ทำงานปกติหรือไม่

✔ คืน error JSON ที่อ่านง่าย เช่น

{
  "error": "Too Many Requests",
  "retry_after": 3
}

 


 

⭐ สรุปสุดท้าย

 

Rate Limiting เป็น “เกราะป้องกันหลัก” ของ API
ช่วยป้องกัน:

  • การยิง request ถี่เกิน
  • bot / hacker
  • brute-force
  • overload
  • ค่า server พุ่ง

 

ทั้ง Go และ Node.js มีวิธีทำที่ชัดเจนและคุณสามารถนำโค้ดในบทความนี้ไปใช้งานจริงได้ทันที 🚀

 

🔵 EP.44 (ตอนต่อไป)

 

เชื่อมต่อ Database: SQL & NoSQL ใน JavaScript และ Go

 

คุณจะได้เรียนรู้:

  • เชื่อมต่อ PostgreSQL / MySQL / MongoDB / Redis
  • Code ตัวอย่าง Go Fiber + Node.js Express
  • ORM/Query Builder ที่ควรใช้
  • การจัดการ Connection Pool อย่างถูกต้อง
  • Best Practices สำหรับ Production