Redis، ويسمى أيضًا Remote Dictionary Server، هو قاعدة بيانات مفتوحة المصدر في الذاكرة. وهو نظام تخزين ذو بنية بيانات يعمل على ذاكرة الوصول العشوائي (RAM) الخاصة بالخادم، وهو أسرع بكثير من أسرع محرك أقراص ذو حالة صلبة (SSD). ونتيجة لذلك، فإن Redis سريع الاستجابة للغاية ومناسب تمامًا لتحديد معدل الطلبات.
تحديد معدل الطلبات يحد من عدد المرات التي يمكن للمستخدم فيها طلب مورد من الخادم. تستخدم العديد من الخدمات حدودًا للمعدل لمنع إساءة استخدام الخدمة، مثل عندما يحاول مستخدم إغراق الخادم بحمل زائد. على سبيل المثال، عند استخدام PHP لتطوير API (واجهة برمجة التطبيقات) عامة لتطبيق الويب الخاص بك، فإن قيود المعدل تكون مطلوبة. وذلك لأنه عندما تتيح واجهة برمجة تطبيقات (API) للعامة، فإنك ستترغب في تحديد عدد المرات التي يمكن للفرد فيها تكرار نشاط معين في فترة زمنية معينة. قد يؤدي المستخدمون الذين ليس لديهم سلطة على نظامك إلى إيقافه تمامًا.
يتيح تحديد معدل الطلبات لتطبيقك العمل بسلاسة من خلال رفض طلبات المستخدمين التي تتجاوز حدًا معينًا. إذا كان لديك عدد كبير من العملاء، فإن تحديد المعدل يفرض سياسة الاستخدام العادل التي تسمح لكل مستخدم بالوصول إلى تطبيقك بسرعات عالية. قد يساعدك تحديد المعدل أيضًا في توفير المال في عرض النطاق الترددي عن طريق تقليل الازدحام على الخادم الخاص بك.
من خلال تتبع نشاط المستخدم في قاعدة بيانات مثل MySQL، سيكون من الممكن إنشاء برنامج لتحديد معدل الطلبات. ومع ذلك، نظرًا لأنه يجب تنزيل هذه البيانات من القرص وتقييمها مقابل الحد المحدد، فقد لا تكون النتيجة النهائية قابلة للتطوير عندما يتصل عدة أشخاص بالنظام في نفس الوقت. ليس هذا غير فعال فحسب، بل إن حلول إدارة قواعد البيانات 관계ية لم تُصمم لهذا الغرض.
يعد Redis خيارًا جيدًا لإنشاء محدد معدل الطلبات لأنه يعمل كقاعدة بيانات في الذاكرة وقد تم إثبات موثوقيته في هذا المجال. في هذا البرنامج التعليمي، سنأخذك عبر خطوات تطبيق تحديد معدل الطلبات في PHP باستخدام Redis على Ubuntu 20.04.
لنبدأ!
المتطلبات الأساسية
لمتابعة هذا البرنامج التعليمي، ستحتاج إلى ما يلي:
-
أحدث إصدار من Ubuntu مثبتًا على نظامك.
-
يجب أن يتمتع مستخدمو النظام بـ صلاحيات sudo.
-
حزمة LAMP.
-
قم بإعداد هذا باتباع دليل كيفية إعداد حزمة LAMP التعليمي.
-
-
خادم Redis.
-
اتبع دليل كيفية تثبيت وتأمين خادم Redis لإعداد Redis في نظامك.
-
الخطوة 1: تثبيت امتداد Redis لـ PHP
قبل أن نبدأ، دعنا نحدث المستودعات لتجنب تعارض الحزم:
|
1 |
sudo apt update |
بعد ذلك، قم بتثبيت امتداد php-redis، وهي حزمة تجعل من الممكن استخدام Redis في برامج PHP. قم بتشغيل أمر sudo التالي لتثبيت php-redis:
|
1 |
sudo apt install -y php-redis |
بعد ذلك، أعد تشغيل خادم Apache لتحميل مكتبة php-redis:
|
1 |
sudo systemctl restart apache2 |
الخطوة التالية هي تحديث المعلومات في فهرس البرامج الخاص بك وتثبيت مكتبة Redis لـ PHP. بعد ذلك، سنقوم بإنشاء مورد PHP يقيد الوصول بناءً على عنوان IP الخاص بالمستخدم.
الخطوة 2: إنشاء مورد ويب PHP لتحديد معدل الطلبات
في هذه الخطوة، ستقوم بإنشاء ملف demo.php في الدليل الجذري لخادم الويب الخاص بك ( /var/www/html/). سيكون هذا الملف متاحًا للعامة، وسيتمكن المستخدمون من تشغيل عنوان URL في متصفح الويب المفضل لديهم. لاحقًا، سنستخدم أمر curl للتحقق من إمكانية الوصول إلى المورد الذي نريد استخدامه. يمكن للمستخدمين الوصول إلى ملف المورد النموذجي ثلاث مرات في غضون 15 ثانية. أي محاولة تتجاوز الحد الأقصى ستؤدي إلى ظهور رسالة خطأ.
تعتمد الوظيفة الأساسية لهذا الملف بشكل كبير على خادم Redis. يقوم كود PHP الموجود في الملف بإنشاء مفتاح على خادم Redis اعتمادًا على عنوان IP الخاص بالمستخدم عندما يصل المستخدم إلى المورد لأول مرة. سيحاول الكود مطابقة عنوان IP الخاص بالمستخدم مع المفاتيح المحفوظة في خادم Redis وزيادة القيمة بمقدار واحد إذا كان المفتاح موجودًا عندما يعود المستخدم إلى المورد. سيستمر كود PHP في التحقق لمعرفة ما إذا كانت القيمة الجديدة قد وصلت إلى الحد الأقصى.
بعد 15 ثانية، ستنتهي صلاحية مفتاح Redis، الذي يعتمد على عنوان IP الخاص بالمستخدم، وسيبدأ تتبع زيارات المستخدم لمورد الويب مرة أخرى. افتح /var/www/html/demo.php ملف في nano محرر النصوص:
|
1 |
sudo nano /var/www/html/demo.php |
ثم املأ جميع الحقول لتهيئة فئة Redis. لا تنسَ تعيين REDIS_PASSWORD على القيمة الصحيحة:
|
1 2 3 4 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); |
Redis->auth يدعم مصادقة النص الصريح لخادم Redis. يعمل هذا بشكل جيد إذا كنت تعمل محليًا (من خلال localhost)، ولكن إذا كنت تتعامل مع خادم Redis بعيد، مصادقة SSL يوصى بها.
بعد ذلك، في نفس الملف، قم بتعيين المتغيرات التالية إلى قيمها الافتراضية:
|
1 2 3 4 5 |
. . . $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; |
دعنا نفهم هذه العبارات بالتفصيل:
-
$max_calls_limit: لا يمكن للمستخدم الوصول إلى المورد بعد هذا الحد الأقصى للاستدعاءات.
-
$time_period: يُستخدم هذا كإطار زمني ويُحسب بالثواني. هنا، يُسمح للمستخدم بالوصول إلى المورد وفقًا للحدود المحددة في $max_calls_limit .
-
$total_user_calls: يجمع عدد المرات التي طلب فيها المستخدم الوصول إلى الاستدعاءات حد في فترة زمنية معينة.
ثم، أضف الكود التالي للحصول على عنوان IP الخاص بالطلب الذي يطلب الوصول إلى صفحة الويب:
|
1 2 3 4 5 6 7 8 9 10 |
. . . if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $user_ip_address = $_SERVER['HTTP_CLIENT_IP']; } elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $user_ip_address = $_SERVER['REMOTE_ADDR']; } |
كتوضيح، يقوم هذا الكود بتسجيل إجراءات المستخدمين حسب عناوين IP الخاصة بهم. إذا كان لديك مورد محمي على الخادم يتطلب مصادقة، فيمكنك تتبع إجراءات المستخدمين باستخدام أسماء المستخدمين أو رموز الوصول الخاصة بهم.
في دليلنا، سيتم تخصيص معرف فريد لكل مستخدم يقوم بتسجيل الدخول إلى نظامك (على سبيل المثال، معرف العميل، أو معرف المطور، أو معرف البائع، أو حتى معرف المستخدم). تذكر استخدام هذه المعرفات بدلاً من $user_ip address إذا كنت تتابع برنامجنا التعليمي.
هنا، يعد عنوان IP الخاص بالمستخدم كافيًا لتوضيح الفكرة. أضف كتلة الكود التالية إلى ملفك بمجرد حصولك على عنوان IP الخاص بالمستخدم من مقتطف الكود السابق:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
. . . if (!$redis->exists($user_ip_address)) { $redis->set($user_ip_address, 1); $redis->expire($user_ip_address, $time_period); $total_user_calls = 1; } else { $redis->INCR($user_ip_address); $total_user_calls = $redis->get($user_ip_address); if ($total_user_calls > $max_calls_limit) { echo "المستخدم " . $user_ip_address . " تجاوز الحد المسموح به."; exit(); } } echo "مرحبًا " . $user_ip_address . " إجمالي الاستدعاءات التي تم إجراؤها " . $total_user_calls . " في " . $time_period . " ثوانٍ"; |
فيما يلي نظرة عامة على هذه العبارات:
-
if...else: تتحقق هذه العبارة مما إذا كان هناك مفتاح محدد بعنوان IP على خادم Redis.
-
إذا لم يتم العثور على المفتاح، فإن (!$redis->exists($user_ip_address)) {...}، يمكنك تعيين المفتاح وتحديد قيمته إلى 1 باستخدام $redis->set($user_ip_address, 1).
-
-
$redis->expire($user_ip_address, $time_period): يحدد وقت انتهاء صلاحية المفتاح في وقت محدد. هنا في هذا البرنامج التعليمي، قمنا بتعيينه إلى 15 ثوانٍ.
-
إذا لم يتم العثور على عنوان IP الخاص بالمستخدم في مفتاح Redis، فقم بتعيين قيمة المتغير $total_user_calls قيمة كـ 1.
-
else {...}: تستخدم كتلة العبارة الأمر $redis->INCR($user_ip_address); لزيادة قيمة مفتاح Redis بمقدار 1. سيتم تطبيق هذا على كل عنوان IP مرتبط بالمفتاح.
-
ملاحظة: يمكنك تحقيق ذلك فقط عندما يكون المفتاح معينًا بالفعل في خادم Redis ويتم احتسابه كطلب متكرر.
-
-
$total_user_calls = $redis->get($user_ip_address): تسترد هذه العبارة إجمالي الطلبات من خلال التحقق من المفتاح الخاص بها والمستند إلى عنوان IP على خادم Redis.
-
if ($total_user_calls > $max_calls_limit) {... }..: تُستخدم عبارة if هذه للتحقق من تجاوز الحد المسموح به. إذا كان الأمر كذلك، فستقوم بإخطار المستخدم بـ echo "المستخدم" . $user_ip_address . " تم تجاوز الحد المسموح به.";.
أخيرًا، تقوم بإخطار المستخدم بعدد زياراته في فترة محددة باستخدام عبارة echo "مرحبًا" . $user_ip_address . "إجمالي الطلبات المقدمة" . $total_user_calls . "في" . $time_period . "ثوانٍ"; .
بعد ذلك، أضف أسطر الكود التالية في ملف /var/www/html/demo.php الخاص بك:
|
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 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $user_ip_address = $_SERVER['HTTP_CLIENT_IP']; }elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $user_ip_address = $_SERVER['REMOTE_ADDR']; } if (!$redis->exists($user_ip_address)) { $redis->set($user_ip_address, 1); $redis->expire($user_ip_address, $time_period); $total_user_calls = 1; } else { $redis->INCR($user_ip_address); $total_user_calls = $redis->get($user_ip_address); if ($total_user_calls > $max_calls_limit) { echo "المستخدم " . $user_ip_address . " تم تجاوز الحد المسموح به."; exit(); } } echo "مرحبًا " . $user_ip_address . " إجمالي الطلبات المقدمة " . $total_user_calls . " في " . $time_period . " ثوانٍ"; ?> |
احفظ وأغلق ملف /var/www/html/demo.php بعد الانتهاء من تعديله. على صفحة الويب demo.php، لقد قمت الآن بإنشاء المنطق المطلوب لتحديد معدل طلبات المستخدمين. دعنا نختبر السكربت الخاص بنا في الخطوة التالية.
الخطوة 3: تشغيل اختبار تحديد معدل Redis
ستستخدم الأمر curl في هذه الخطوة لطلب مورد الويب الذي كتبته في الخطوة 2. لاختبار السكربت بدقة، أصدر أمرًا واحدًا يطلب المورد خمس مرات. يمكن تحقيق ذلك عن طريق إضافة وسيطة عنوان URL نائبة إلى demo.php نهاية الملف. لتنفيذ curl التعليمات خمس مرات، استخدم القيمة ?[1-5] في نهاية طلبك.
نفذ ما يلي curl الأمر أدناه:
|
1 |
curl -H "Accept: text/plain" -H "Content-Type: text/plain" -X GET http://localhost/demo.php?[1-5] |
عند تنفيذ الكود، يجب أن تحصل على شيء مثل هذا:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[1/5]: http://localhost/demo.php?1 --> <stdout> --_curl_--http://localhost/demo.php?1 مرحباً 127.0.0.1 إجمالي الطلبات التي تم إجراؤها 1 في 15 ثوانٍ [2/5]: http://localhost/demo.php?2 --> <stdout> --_curl_--http://localhost/demo.php?2 مرحباً 127.0.0.1 إجمالي الطلبات التي تم إجراؤها 2 في 15 ثوانٍ [3/5]: http://localhost/demo.php?3 --> <stdout> --_curl_--http://localhost/demo.php?3 مرحباً 127.0.0.1 إجمالي الطلبات التي تم إجراؤها 3 في 15 ثوانٍ [4/5]: http://localhost/demo.php?4 --> <stdout> --_curl_--http://localhost/demo.php?4 المستخدم 127.0.0.1 الحد تم تجاوزه. [5/5]: http://localhost/demo.php?5 --> <stdout> --_curl_--http://localhost/demo.php?5 المستخدم 127.0.0.1 الحد تم تجاوزه. |
لقد تمت الطلبات الثلاثة الأولى، كما ترى، دون أي مشاكل. ومع ذلك، تم تحديد معدل الاستعلامين الرابع والخامس بواسطة البرنامج النصي الخاص بك. هناك احتمال كبير أن يقوم خادم Redis بإبطاء السرعة التي يمكن للأشخاص إجراء الاستعلامات بها.
لقد قمت بتحديد قيم منخفضة للمتغيرين المذكورين أدناه في هذا الدليل:
|
1 2 3 4 |
... $max_calls_limit = 3; $time_period = 15; ... |
عند إنشاء تطبيقك في بيئة الإنتاج، قد ترغب في التفكير في استخدام أرقام أكبر، اعتماداً على عدد المرات التي تعتقد أن الأشخاص سيستخدمونه فيها.
من الجيد فحص الإحصاءات في الوقت الفعلي قبل تعديل هذه الأرقام. في هذا المثال، إذا أظهرت سجلات الخادم الخاص بك أن المستخدم العادي يزور تطبيقك 1,000 مرة كل 60 ثانية، فيمكنك استخدام هذا الرقم كمثال على مقدار تقييد المعدل الذي يجب استخدامه.
الخاتمة
في هذا الدليل، تعلمت كيفية استخدام خادم Redis مع PHP على Ubuntu 20.04. بينما يوضح هذا المنشور كيفية عمل تحديد المعدل مع Redis، يمكنك تخصيصه لتلبية متطلبات تطبيق الويب الخاص بك. نحن نشجعك على استكشاف أمثلة من العالم الحقيقي مثل الحد الأقصى لطلبات Twitter, واجهة برمجة تطبيقات البحث المخصص JSON من Google، وغيرها من المستندات المماثلة لتعزيز معرفتك بتحديد المعدل ومحاولة التجربة بنفسك باستخدام حدود زمنية مختلفة.
علاوة على ذلك، هناك العديد من المواد التعليمية الأخرى حول Redis و PHP والتي يمكنك الوصول إليها من مدوناتنا:
- نشر تطبيق PHP على عنقود Kubernetes باستخدام Ubuntu 18.04
- تثبيت وتأمين PHPmyadmin على Ubuntu 20.04
- كيفية تثبيت حزمة LEMP (Linux Nginx MySQL PHP) على Ubuntu 20.04
حوسبة سعيدة!
التعليقات
لا توجد تعليقات بعد. كن أول من يعلق.