تحديد معدل الطلبات في Go: دليل للحد من سرعة الطلبات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تحديد معدل الطلبات في Go: دليل شامل للحد من سرعة الطلبات

\n\n

تحديد معدل الطلبات (Rate Limiting) هو آلية أساسية للحماية وإدارة الحمل في تطبيقات الويب الحديثة والخدمات المصغرة. في لغة Go (Golang)، توجد العديد من الأساليب والمكتبات لتطبيق تحديد معدل الطلبات، من البسيطة إلى المتقدمة. في هذه المقالة، سنشرح المفاهيم الأساسية والمكتبات الشائعة ونعرض أمثلة على الكود.

\n\n

ما هو تحديد معدل الطلبات ولماذا هو مطلوب؟

\n\n

تحديد معدل الطلبات هو تقنية للتحكم في عدد الطلبات التي يمكن للعميل إرسالها خلال فترة زمنية محددة. الأهداف الرئيسية:

\n\n
    \n
  • الحماية من هجمات DDoS — منع تحميل الخادم الزائد
  • \n
  • التوزيع العادل للموارد — وصول متساوٍ لجميع المستخدمين
  • \n
  • توفير الموارد — تقليل تكاليف البنية التحتية
  • \n
  • منع إساءة الاستخدام — الحماية من السكرابينغ والهجمات القسرية
  • \n
\n\n

الخوارزميات الأساسية لتحديد معدل الطلبات

\n\n

توجد عدة خوارزميات كلاسيكية، لكل منها مزاياها:

\n\n
    \n
  • Token Bucket (دلو الرموز) — الخوارزمية الأكثر شيوعًا، حيث تتراكم "الرموز" بمعدل معين
  • \n
  • Leaky Bucket (الدلو المتسرب) — تتم معالجة الطلبات بمعدل ثابت، ويتم تجاهل الفائض
  • \n
  • Fixed Window (النافذة الثابتة) — عداد بسيط للطلبات خلال فترة زمنية ثابتة
  • \n
  • Sliding Window (النافذة المنزلقة) — أكثر دقة من النافذة الثابتة، مع مراعاة الحدود الزمنية
  • \n
\n\n

المكتبات الشائعة لتحديد معدل الطلبات في Go

\n\n

1. المكتبة القياسية: golang.org/x/time/rate

\n\n

هذا امتداد رسمي من فريق Go، يطبق خوارزمية Token Bucket. إنها خفيفة الوزن وسهلة الاستخدام ومناسبة تمامًا لمعظم السيناريوهات.

\n\n
package main\n\nimport (\n    "fmt"\n    "net/http"\n    "time"\n    "golang.org/x/time/rate"\n)\n\nfunc main() {\n    // إنشاء محدد: طلبان في الثانية، مع burst 5\n    limiter := rate.NewLimiter(2, 5)\n\n    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {\n        if !limiter.Allow() {\n            http.Error(w, "طلبات كثيرة جدًا", http.StatusTooManyRequests)\n            return\n        }\n        fmt.Fprintf(w, "OK: %s", time.Now().Format(time.RFC3339))\n    })\n\n    http.ListenAndServe(":8080", nil)\n}
\n\n

2. github.com/ulule/limiter

\n\n

مكتبة أكثر مرونة مع دعم مخازن مختلفة (Redis، Memcached، in-memory) وخوارزميات. مناسبة للأنظمة الموزعة.

\n\n
import (\n    "github.com/gin-gonic/gin"\n    "github.com/ulule/limiter/v3"\n    "github.com/ulule/limiter/v3/drivers/store/memory"\n)\n\nfunc main() {\n    // الإعداد: 10 طلبات في الثانية\n    rate := limiter.Rate{\n        Period: 1 * time.Second,\n        Limit:  10,\n    }\n\n    store := memory.NewStore()\n    instance := limiter.New(store, rate)\n\n    r := gin.Default()\n    r.Use(func(c *gin.Context) {\n        key := c.ClientIP()\n        context, err := instance.Get(c.Request.Context(), key)\n        if err != nil {\n            c.AbortWithStatusJSON(500, gin.H{"error": "خطأ داخلي"})\n            return\n        }\n        if context.Reached {\n            c.AbortWithStatusJSON(429, gin.H{"error": "طلبات كثيرة جدًا"})\n            return\n        }\n        c.Next()\n    })\n\n    r.Run(":8080")\n}
\n\n

3. github.com/juju/ratelimit

\n\n

مكتبة بسيطة وموثوقة من Canonical، تعتمد على خوارزمية Token Bucket. تتميز بواجهة برمجة تطبيقات بسيطة.

\n\n
import (\n    "github.com/juju/ratelimit"\n    "time"\n)\n\nfunc main() {\n    // إنشاء bucket: 100 رمز، إعادة تعبئة 10 رموز في الثانية\n    bucket :=                    

توصيات