تحديد المعدل في Kotlin: المكتبات والاستراتيجيات والأمثلة العملية
\n\nتحديد المعدل (تقييد سرعة الطلبات) هو آلية بالغة الأهمية لحماية واجهات API والخدمات المصغرة وتطبيقات الويب من الأحمال الزائدة وهجمات DDoS والارتفاعات المفاجئة في حركة المرور. في نظام Kotlin البيئي، الذي يعمل فوق JVM، توجد عدة مكتبات ناضجة تسمح بتنفيذ هذه المنطق بمرونة. في هذه المقالة، سنستعرض ثلاثة مناهج وأدوات رئيسية: Bucket4j، Resilience4j و RateLimiter المدمج من Guava.
\n\n1. Bucket4j — تنفيذ متقدم لـ Token Bucket
\n\nBucket4j هي مكتبة Java متوافقة تمامًا مع Kotlin. وهي تنفذ خوارزمية Token Bucket (سلة الرموز) وتدعم التقييد المحلي والموزع (عبر Redis، Hazelcast، Infinispan).
\n\nالإمكانيات الرئيسية:
\n- \n
- تحديد عدد الرموز وسرعة إعادة تعبئتها. \n
- دعم "الانفجارات" (الارتفاعات القصيرة) من خلال تراكم الرموز. \n
- العمل في بيئة متعددة الخيوط دون أقفال. \n
- التكامل مع Spring Boot عبر المُشغّل
bucket4j-spring-boot-starter. \n
مثال على محدد معدل بسيط في Kotlin:
\nimport io.github.bucket4j.Bandwidth\nimport io.github.bucket4j.Bucket\nimport io.github.bucket4j.Refill\nimport java.time.Duration\n\nfun main() {\n // 10 طلبات في الدقيقة، مع إمكانية تراكم حتى 20 رمزًا\n val limit = Bandwidth.classic(20, Refill.greedy(10, Duration.ofMinutes(1)))\n val bucket = Bucket.builder()\n .addLimit(limit)\n .build()\n\n // التحقق من توفر الرمز\n if (bucket.tryConsume(1)) {\n println("✅ الطلب مسموح به")\n } else {\n println("❌ تم تجاوز الحد، حاول لاحقًا")\n }\n}\n\nللسيناريو الموزع (على سبيل المثال، عدة نسخ من الخدمة المصغرة) استخدم Bucket4j مع Redis:
\nimport io.github.bucket4j.distributed.proxy.ProxyManager\nimport io.github.bucket4j.redis.lettuce.Bucket4jLettuce\nimport io.lettuce.core.RedisClient\n\nval redisClient = RedisClient.create("redis://localhost:6379")\nval proxyManager: ProxyManager<String> = Bucket4jLettuce\n .builder(redisClient)\n .build()\n\nval bucket = proxyManager.builder()\n .build("user:123", Bucket4jConfiguration(\n Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(1)))\n ))\n\n\n2. Resilience4j — RateLimiter كجزء من Circuit Breaker
\n\nResilience4j هي مكتبة مرونة شائعة لـ Java/Kotlin، لا تشمل فقط محدد المعدل، بل أيضًا circuit breaker و retry و bulkhead. تعمل وحدة RateLimiter الخاصة بها بناءً على خوارزمية Sliding Window (النافذة المنزلقة).
الميزات:
\n- \n
- تكامل سهل مع coroutines في Kotlin عبر دوال
suspend. \n - تحديد فترة النافذة وحد الطلبات. \n
- معالجة مرنة للأخطاء: إرجاع استثناء، fallback، أو انتظار. \n
مثال مع coroutines:
\nimport io.github.resilience4j.ratelimiter.RateLimiter\nimport io.github.resilience4j.ratelimiter.RateLimiterConfig\nimport io.github.resilience4j.kotlin.ratelimiter.awaitRateLimiter\nimport java.time.Duration\nimport kotlinx.coroutines.runBlocking\n\nval config = RateLimiterConfig.custom()\n .limitForPeriod(10) // 10 طلبات\n .limitRefreshPeriod(Duration.ofSeconds(1)) // خلال ثانية واحدة\n .timeoutDuration(Duration.ofMillis(500)) // مهلة الانتظار\n .build()\n\nval rateLimiter = RateLimiter.of("api-limiter", config)\n\nsuspend fun fetchData(): String {\n return awaitRateLimiter(rateLimiter) {\n // استدعاء API الخاص بك\n "تم الحصول على البيانات"\n }\n}\n\nfun main() = runBlocking {\n val result = fetchData()\n p