في هذا المنشور سوف نتعلم كيفية استخدام المشرف للتعامل مع تنفيذ أمر Symfony. في الأساس، سوف يسمح لنا المشرف بما يلي:
نلجأ أحيانًا إلى Unix crontab لأتمتة تنفيذ العمليات. قد ينجح هذا في معظم الأوقات ولكن قد تكون هناك مواقف يمكن أن تسبب فيها مشكلات.
لنتخيل أن لدينا جدول قاعدة بيانات يسجل إشعارات المستخدمين. يخزن الجدول المعلومات التالية:
من ناحية أخرى، قمنا بتشفير أمر يتبع تنفيذه الخطوات التالية:
قمنا بتعيين هذا الأمر في crontab لنظام التشغيل Linux ليتم تشغيله بين الحين والآخر (دقيقة واحدة أو دقيقتين وما إلى ذلك). حتى الان جيدة جدا.
الآن لنتخيل أن العملية الحالية استعلمت عن 500 إشعار وعندما أرسلت 400، تبدأ عملية جديدة. وهذا يعني أن العملية الجديدة ستقوم بالاستعلام عن 100 إشعار لم يتم تحديثها بعد من خلال العملية الأخيرة بالإضافة إلى الإشعارات الجديدة:
يمكن أن يتسبب هذا في إرسال تلك الإشعارات المائة مرتين نظرًا لأن كلتا العمليتين قد استعلمتا عنها.
كحل، يمكننا اللجوء إلى استخدام المشرف. سيبقي عمليتنا قيد التشغيل وسيعيد تشغيلها عند الحاجة. بهذه الطريقة، نحتفظ بعملية واحدة فقط ونتجنب التداخل. دعنا نحلل كيف يجب أن يبدو الأمر:
#[AsCommand( name: 'app:notification' )] class NotificationCommand extends Command { private bool $forceFinish = false; protected function configure(): void { $this ->addOption('time-limit', null, InputOption::VALUE_OPTIONAL, 'Max time alive in seconds') ->addOption('time-between-calls', null, InputOption::VALUE_OPTIONAL, 'Time between every loop call') ; } protected function execute(InputInterface $input, OutputInterface $output): int { $this->forceFinish = false; pcntl_signal(SIGTERM, [$this, 'signalHandler']); pcntl_signal(SIGINT, [$this, 'signalHandler']); $timeLimit = $input->getOption('time-limit'); $timeBetweenCalls = $input->getOption('time-between-calls'); $dtMax = (new \DateTimeImmutable())->add(\DateInterval::createFromDateString(" {$timeLimit} seconds")); do{ // Here we should execute a service to query and send notifications // ...... sleep($timeBetweenCalls); $dtCurrent = new \DateTimeImmutable(); }while($dtCurrent forceFinish); return Command::SUCCESS; } public function signalHandler(int $signalNumber): void { echo 'Signal catch: ' . $signalNumber . PHP_EOL; match ($signalNumber) { SIGTERM, SIGINT => $this->forceFinish = true, default => null }; } }
دعونا نشرح الأمر خطوة بخطوة:
تعلن طريقة التكوين عن خيارات الإدخال:
طريقة التنفيذ تعمل على النحو التالي:
بالتقاط إشارات SIGTERM وSIGINT Unix. SIGINT هي الإشارة المرسلة عندما نضغط على Ctrl C وSIGTERM هي الإشارة الافتراضية عندما نستخدم أمر الإيقاف. عندما تكتشفها الدالة signalHandler، فإنها تقوم بتعيين المتغير forceFinish على القيمة true بحيث، عند انتهاء الحلقة الحالية، سينتهي الأمر لأن المتغير forceFinish هو لم تعد كاذبة. يتيح ذلك للمستخدمين إنهاء العملية دون الحاجة إلى الانتظار حتى انتهاء الحد الأقصى للتاريخ.
sudo apt update && sudo apt install مشرف
sudo apt update && sudo apt install supervisor
مشرف الحالة sudo systemctl
sudo systemctl status supervisor/etc/supervisor/conf.d
. لنقم بإنشاء ملف باسم notif.conf ولصق المحتوى التالي:
command=php
command=php/bin/console app:notifications --time-limit=120 --time-between-calls=10 user= numprocs=1 autostart=true autorestart=true process_name=%(program_name)s_%(process_num)02d
لمدة أقصاها 120 ثانية، وسيظل في وضع السكون لمدة 10 ثوانٍ بعد كل حلقة. بعد مرور 120 ثانية أو تخزين إشارة يونكس مؤقتًا، سيخرج الأمر من الحلقة وينتهي. ثم سيبدأ المشرف في ذلك مرة أخرى. خاتمة
في الكتاب الأخير الذي كتبته، أوضحت كيفية استخدام المشرف للحفاظ على تشغيل عمال المراسلة في Symfony. إذا كنت تريد معرفة المزيد، يمكنك العثور على الكتاب هنا: إنشاء واجهة برمجة تطبيقات موجهة نحو العمليات باستخدام PHP وإطار عمل Symfony: دليل خطوة بخطوة
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3