مقدمة: لماذا التزامن في PHP ليس أسطورة
\nتُعتبر PHP تقليديًا لغة متزامنة، حيث تتم معالجة كل طلب بشكل تسلسلي. ومع ذلك، تتطلب التطبيقات الحديثة - من معالجة الفيديو إلى تحليل البيانات الضخمة - تنفيذ مهام متعددة في وقت واحد. بدون التزامن، فإنك تخاطر بالاصطدام بـ"جدار الأداء"، حيث يظل الخادم القوي خاملاً في انتظار اكتمال عمليات الإدخال/الإخراج.
\nفي هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التزامن في PHP: من استدعاءات النظام إلى إضافات مستوى النواة. ستتعلم كيفية جعل PHP يعمل بشكل متوازٍ دون فقدان السيطرة على الموارد.
\n\n1. الأساسيات: العمليات مقابل الخيوط في PHP
\nقبل الغوص في الكود، من المهم فهم الفرق بين العمليات والخيوط في سياق PHP.
\n- \n
- العمليات - نسخ معزولة، لكل منها ذاكرتها الخاصة. يتم إنشاؤها عبر
pcntl_fork(). مناسبة للمهام الثقيلة، ولكنها تتطلب تواصلاً بين العمليات (IPC). \n - الخيوط - "مهام فرعية" خفيفة الوزن داخل عملية واحدة، تشارك الذاكرة. يتم تنفيذها عبر إضافة
pthreads. مثالية للعمل مع البيانات المشتركة، ولكنها تتطلب مزامنة. \n
للمستوى المتقدم، من المهم معرفة كيفية الجمع بين كلا النهجين. على سبيل المثال، استخدام التفرع (forking) لعزل المهام الحرجة، والخيوط للمعالجة المتوازية داخل سياق واحد.
\n\n1.1 العمليات المتوازية عبر pcntl_fork()
\nاستدعاء النظام pcntl_fork() ينشئ عملية فرعية تنسخ ذاكرة العملية الأم. لنلقِ نظرة على مثال للمعالجة المتوازية لعناوين URL متعددة:
<?php\n$urls = ['https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];\n$pids = [];\n\nforeach ($urls as $url) {\n $pid = pcntl_fork();\n if ($pid == -1) {\n die('فشل إنشاء العملية');\n } elseif ($pid) {\n // العملية الأم: حفظ PID\n $pids[] = $pid;\n } else {\n // العملية الفرعية: تنفيذ التحميل\n $data = file_get_contents($url);\n file_put_contents('/tmp/' . md5($url) . '.json', $data);\n exit(0); // إنهاء العملية الفرعية\n }\n}\n\n// انتظار اكتمال جميع العمليات\nforeach ($pids as $pid) {\n pcntl_waitpid($pid, $status);\n}\necho "تمت معالجة جميع عناوين URL بشكل متوازٍ!";\n?>\nهام: بعد fork()، ترث العمليات الفرعية جميع واصفات الملفات المفتوحة واتصالات قاعدة البيانات. أغلقها بشكل صريح في العملية الفرعية لتجنب التعارضات.
\n\n2. المهام غير المتزامنة مع ReactPHP و Amp
\nلتطبيقات الويب حيث تكون الاستجابة مهمة، استخدم مكتبات حلقة الأحداث الموجهة. ReactPHP و Amp تسمحان بتنفيذ عمليات غير محظورة دون إنشاء عمليات منفصلة.
\n\n2.1 مثال مع ReactPHP
\nقم بتثبيت المكتبة عبر Composer: composer require react/react. أدناه - عميل HTTP غير متزامن يرسل ثلاثة طلبات في وقت واحد:
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$urls = ['http://example.com', 'http://example.org', 'http://example.net'];\n$promises = [];\n\nforeach ($urls as $url) {\n $request = $client->request('GET', $url);\n $request->on('response', function ($response) use ($url) {\n echo "الرد من {$url}: " . $response->getCode() . PHP_EOL;\n });\n $request->end();\n}\n\n$loop->run();\n?>\nينشئ ReactPHP حلقة أحداث واحدة تعالج جميع الطلبات دون حظر. هذا مثالي لبوابات API أو الخدمات المصغرة حيث تكون سرعة الاستجابة مهمة.
\n\n3. إدارة الخيوط مع pthreads (بناء ZTS)
\nإضافة pthreads هي الطريقة الوحيدة للحصول على تعدد خيوط حقيقي في PHP.
المدونات
توصيات الكتب
اقرأ أيضًا