Reload Policy Dinamis & Tiering
Rate limiter tradisional membutuhkan restart aplikasi atau lock global mutex untuk memperbarui aturan rate limit. distlimit menghadirkan Engine Dynamic Policy Lock-Free yang didukung oleh atomic.Pointer[Policy] Go untuk pembaruan aturan zero-downtime dan resolusi tier multi-tenant.
⚡ Reload Policy Runtime (UpdatePolicy)
Section titled “⚡ Reload Policy Runtime (UpdatePolicy)”Panggil limiter.UpdatePolicy(newLimit, newWindow) di mana saja dalam kode Anda untuk memperbarui limit global secara instan:
package main
import ( "net/http" "time"
"github.com/balramadan/distlimit" "github.com/balramadan/distlimit/driver/memory")
func main() { memDriver := memory.New(5 * time.Minute)
// Inisialisasi Limiter dengan aturan default: 100 request per menit limiter, _ := distlimit.New( memDriver, distlimit.WithLimit(100), distlimit.WithWindow(1*time.Minute), )
// Endpoint API Admin untuk memperbarui limit secara dinamis http.HandleFunc("/admin/update-limits", func(w http.ResponseWriter, r *http.Request) { // Langsung perbarui limit menjadi 500 req/menit saat runtime tanpa jeda lock limiter.UpdatePolicy(500, 1*time.Minute) w.Write([]byte("Kebijakan rate limit berhasil diperbarui!")) })}Cara Kerja Di Belakang Layar
Section titled “Cara Kerja Di Belakang Layar”sequenceDiagram
autonumber
actor Admin
participant Limiter as Limiter (atomic.Pointer)
actor Goroutine as HTTP Worker Goroutines
Admin->>Limiter: UpdatePolicy(500, 1m)
Limiter->>Limiter: Alokasi struct Policy baru
Limiter->>Limiter: atomic.Pointer.Store(&newPolicy)
Goroutine->>Limiter: AllowKey(ctx, key)
Limiter->>Goroutine: atomic.Pointer.Load() -> Evaluasi 500 req/m
Karena penggantian pointer dieksekusi via operasi atomik CPU, goroutine worker aktif yang membaca kebijakan mengalami zero lock contention (latensi nanodetik $O(1)$).
👑 Resolusi Tier Multi-Tenant (PolicyResolver)
Section titled “👑 Resolusi Tier Multi-Tenant (PolicyResolver)”Dalam platform SaaS multi-tenant, tier pengguna yang berbeda (misal Free, Pro, Enterprise) membutuhkan aturan rate limit kustom tanpa perlu membuat instance limiter yang terpisah.
Interface PolicyResolver memungkinkan Anda menyelesaikan aturan Policy dinamis per key secara realtime:
type PolicyResolver interface { ResolvePolicy(ctx context.Context, key string) (Policy, bool)}Contoh Implementasi
Section titled “Contoh Implementasi”package main
import ( "context" "strings" "time"
"github.com/balramadan/distlimit" "github.com/balramadan/distlimit/driver/memory")
// Implementasi Custom Tier Resolvertype CustomTierResolver struct{}
func (r *CustomTierResolver) ResolvePolicy(ctx context.Context, key string) (distlimit.Policy, bool) { // Key VIP Enterprise mendapatkan 10.000 request per menit if strings.HasPrefix(key, "vip:") { return distlimit.Policy{ Limit: 10000, Window: 1 * time.Minute, }, true }
// Pengguna Pro mendapatkan 1.000 request per menit if strings.HasPrefix(key, "pro:") { return distlimit.Policy{ Limit: 1000, Window: 1 * time.Minute, }, true }
// Fallback: kembalikan false untuk menggunakan kebijakan default Limiter return distlimit.Policy{}, false}
func main() { memDriver := memory.New(5 * time.Minute)
// Pasangkan PolicyResolver ke Limiter limiter, _ := distlimit.New( memDriver, distlimit.WithLimit(100), // Kebijakan default untuk pengguna Free / Anonim distlimit.WithWindow(1*time.Minute), distlimit.WithPolicyResolver(&CustomTierResolver{}), )
// Contoh evaluasi: limiter.AllowKey(context.Background(), "user:123") // Menggunakan limit default (100 req/m) limiter.AllowKey(context.Background(), "pro:456") // Diselesaikan ke limit Pro (1.000 req/m) limiter.AllowKey(context.Background(), "vip:789") // Diselesaikan ke limit VIP (10.000 req/m)}