التزامن وتعدد الخيوط في PHP: المستوى المتقدم

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

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

ابدأ الدورة

مقدمة: لماذا التزامن في PHP ليس أسطورة

\n

تُعتبر PHP تقليديًا لغة متزامنة، حيث تتم معالجة كل طلب بشكل تسلسلي. ومع ذلك، تتطلب التطبيقات الحديثة - من معالجة الفيديو إلى تحليل البيانات الضخمة - تنفيذ مهام متعددة في وقت واحد. بدون التزامن، فإنك تخاطر بالاصطدام بـ"جدار الأداء"، حيث يظل الخادم القوي خاملاً في انتظار اكتمال عمليات الإدخال/الإخراج.

\n

في هذه المقالة، سنستعرض التقنيات المتقدمة للعمل مع التزامن في PHP: من استدعاءات النظام إلى إضافات مستوى النواة. ستتعلم كيفية جعل PHP يعمل بشكل متوازٍ دون فقدان السيطرة على الموارد.

\n\n

1. الأساسيات: العمليات مقابل الخيوط في PHP

\n

قبل الغوص في الكود، من المهم فهم الفرق بين العمليات والخيوط في سياق PHP.

\n
    \n
  • العمليات - نسخ معزولة، لكل منها ذاكرتها الخاصة. يتم إنشاؤها عبر pcntl_fork(). مناسبة للمهام الثقيلة، ولكنها تتطلب تواصلاً بين العمليات (IPC).
  • \n
  • الخيوط - "مهام فرعية" خفيفة الوزن داخل عملية واحدة، تشارك الذاكرة. يتم تنفيذها عبر إضافة pthreads. مثالية للعمل مع البيانات المشتركة، ولكنها تتطلب مزامنة.
  • \n
\n

للمستوى المتقدم، من المهم معرفة كيفية الجمع بين كلا النهجين. على سبيل المثال، استخدام التفرع (forking) لعزل المهام الحرجة، والخيوط للمعالجة المتوازية داخل سياق واحد.

\n\n

1.1 العمليات المتوازية عبر pcntl_fork()

\n

استدعاء النظام pcntl_fork() ينشئ عملية فرعية تنسخ ذاكرة العملية الأم. لنلقِ نظرة على مثال للمعالجة المتوازية لعناوين URL متعددة:

\n
<?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\n

2. المهام غير المتزامنة مع ReactPHP و Amp

\n

لتطبيقات الويب حيث تكون الاستجابة مهمة، استخدم مكتبات حلقة الأحداث الموجهة. ReactPHP و Amp تسمحان بتنفيذ عمليات غير محظورة دون إنشاء عمليات منفصلة.

\n\n

2.1 مثال مع ReactPHP

\n

قم بتثبيت المكتبة عبر Composer: composer require react/react. أدناه - عميل HTTP غير متزامن يرسل ثلاثة طلبات في وقت واحد:

\n
<?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\n

3. إدارة الخيوط مع pthreads (بناء ZTS)

\n

إضافة pthreads هي الطريقة الوحيدة للحصول على تعدد خيوط حقيقي في PHP.

المدونات

توصيات الكتب