كيفية تنفيذ المهام غير المتزامنة

السؤال:

كيف يمكن معالجة الأعمال الشاقة بشكل غير متزامن، وتجنب حظر العملية الرئيسية لفترات طويلة. على سبيل المثال، أريد إرسال بريد إلكتروني إلى 1000 مستخدم، هذه العملية بطيئة، قد تستغرق عدة ثوانٍ، وأثناء ذلك، يؤدي حظر العملية الرئيسية إلى التأثير على الطلبات اللاحقة. كيف يمكنني تسليم هذه المهام الشاقة إلى عمليات أخرى لمعالجتها بشكل غير متزامن؟

الإجابة:

يمكنك إنشاء بعض عمليات المهام مسبقًا على جهازك أو على خوادم أخرى أو حتى على مجموعة من الخوادم لمعالجة الأعمال الشاقة. عدد عمليات المهام يمكن أن يكون أكبر، على سبيل المثال 10 أضعاف عدد وحدات المعالجة المركزية، ثم يقرر المستدعي استخدام AsyncTcpConnection لإرسال البيانات بشكل غير متزامن إلى هذه العمليات لمعالجتها بشكل غير متزامن، والحصول على النتائج.

خادم عمليات المهام

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// عامل المهمة، يستخدم بروتوكول نصي
$task_worker = new Worker('Text://0.0.0.0:12345');
// عدد عمليات المهام يمكن أن يكون أكبر حسب الحاجة
$task_worker->count = 100;
$task_worker->name = 'TaskWorker';
$task_worker->onMessage = function(TcpConnection $connection, $task_data)
{
     // لنفترض أن البيانات المرسلة هي json
     $task_data = json_decode($task_data, true);
     // معالجة المنطق الخاص بالمهمة بناءً على task_data.... الحصول على النتيجة، هنا تم تجاهل....
     $task_result = ......
     // إرسال النتيجة
     $connection->send(json_encode($task_result));
};
Worker::runAll();

استدعاء في workerman

use Workerman\Worker;
use \Workerman\Connection\AsyncTcpConnection;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// خدمة websocket
$worker = new Worker('websocket://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $ws_connection, $message)
{
    // إنشاء اتصال غير متزامن مع خدمة المهمة البعيدة، ip هو عنوان خدمة المهمة البعيدة، إذا كانت على نفس الجهاز فهي 127.0.0.1، إذا كانت على مجموعة فهي عنوان lvs
    $task_connection = new AsyncTcpConnection('Text://127.0.0.1:12345');
    // مهمة وبيانات المعلمات
    $task_data = array(
        'function' => 'send_mail',
        'args'       => array('from'=>'xxx', 'to'=>'xxx', 'contents'=>'xxx'),
    );
    // إرسال البيانات
    $task_connection->send(json_encode($task_data));
    // الحصول على النتيجة بشكل غير متزامن
    $task_connection->onMessage = function(AsyncTcpConnection $task_connection, $task_result)use($ws_connection)
    {
         // النتيجة
         var_dump($task_result);
         // تأكد من إغلاق الاتصال غير المتزامن بعد الحصول على النتيجة
         $task_connection->close();
         // إبلاغ العميل websocket المعني بإتمام المهمة
         $ws_connection->send('task complete');
    };
    // تنفيذ الاتصال غير المتزامن
    $task_connection->connect();
};

Worker::runAll();

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