Laravel Horizon
مقدمة
يوفّر Horizon لوحة تحكم جميلة و إعدادات برمجيّة لطوابير (Queues) Laravel المبنيّة على Redis، فهو يوفّر لك مراقبة سهلة للمقاييس الأساسية لنظام الطوابير مثل إنتاجيّة العمل ووقت التشغيل، وفشل المهام.
ستبقى جميع عمليّات الضبط في ملف ضبط واحد وبسيط ممّا يضمن التعاون الكامل بين أعضاء فريقك.
التثبيت
تنبيه: يتطلّب ،Horizon نظرًا لاستخدامه لإشارات العمليّة غير متزامنة، إلى نسخة PHP 7.1 فما فوق. ويجب عليك التأكّد من تعيين محرك الطابور إلى Redis في ملف ضبط الطابور.
يمكنك استخدام Composer
لتثبيت Horizon في مشروع Laravel الخاص بك:
composer require laravel/horizon
بعد تثبيت Horizon، يمكننا استخدام أداة Artisan لنشر الأصول (Assets) باستخدام vendor:publish
:
php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
الضبط
سيتكوّن ملف الضبط الأساسي في config/horizon.php
بعد نشر أصول Horizon، ويسمح لك هذا الملف بضبط خيارات العامل ويحتوي كل خيار ضبط على وصف لعمله، لذا تأكّد من الاطلاع على هذا الملف بشكل جيّد.
خيارات التوازن
يسمح لك Horizon بالاختيار بين ثلاثة استراتيجيات توازن: simple
و auto
و false
. تُقسّم الاستراتيجية simple (والتي هي الافتراضيّة) الوظائف الواردة بالتساوي بين العمليات:
'balance' => 'simple',
تضبط الاستراتيجيّة auto
عدد عمليات العامل لكل طابور بالاعتماد على حجم العمل الحالي في قائمة الانتظار. فعلى سبيل المثال، إذا كان طابور notifications يحتوي على 1000 مهمة قيد الانتظار في حين أن طابور render فارغ، فسيخصص Horizon أكثر عمال لطابور notifications إلى أن ينتهي.
في حالة كان خيار التوازن false
، فسيُستخدم سلوك Laravel الافتراضي، والذي يعالج الطوابير بالترتيب الموجود في ملف الضبط.
استيثاق لوحة التحكم
يعرض Horizon لوحة التحكم في /horizon
، ويمكنك الوصول إلى لوحة التحكم بشكل افتراضي من خلال البيئة المحليّة (local) فقط، ولتحديد سياسة وصول محددة أكثر للوحة التحكم، يمكنك استخدام التابع Horizon::auth
.
يقبل التابع auth رد نداء (callback) والذي يُرجع القيمة true
أو القيمة false
للإشارة ما إذا كان المستخدم يمكنه الوصول إلى لوحة تحكم Horizon، وعادةً، يجب عليك استدعاء التابع Horizon::auth
في التابع boot من AppServiceProvider
:
Horizon::auth(function ($request) {
// return true / false;
});
تشغيل Horizon
بمجرّد ضبط العاملين في ملف الضبط config/horizon.php
، يمكنك بدء تشغيل Horizon باستخدام الأمر Artisan، وهذا الأمر المنفرد سيشغّل جميع العاملين المكوّنين:
php artisan horizon
يمكنك إيقاف عمل Horizon بشكل مؤقت واستئناف عمل المهام باستخدام أوامر Artisan
وهي horizon:pause
و horizon:continue
:
php artisan horizon:pause
php artisan horizon:continue
يمكنك إنهاء عمل Horizon الرئيسي بأمان على جهازك باستخدام أمر horizon:terminate
Artisan، وستكتمل أي مهام يعالجها Horizon ومن ثم سيتوقف:
php artisan horizon:terminate
نشر Horizon على الخادم الإنتاجي
إذا كنت ترغب في نشر Horizon على الخادم الإنتاجي، فيجب عليك ضبط مراقب العمليّة (process monitor) لمراقبة أمر php artisan horizon
وإعادة تشغيله إذا انتهى بشكل غير متوقع.
عند نشر شيفرات برمجيّة جديدة على خادمك، ستحتاج إلى إنهاء Horizon حتى تتمكن من إعادة تشغيله عن طريق مراقب العمليّة Supervisor وتلقي التغييرات الجديدة في الشيفرات البرمجيّة.
ضبط المشرف
إذا كنتَ تستخدم برمجية Supervisor لمراقبة العمليات لكي تدير عملية Horizon. الخاصة بك، فهذا الملف سيكون كافيًا:
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/app.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/app.com/horizon.log
ملاحظة: فكر في استخدام Laravel Forge إذا كنت لا ترغب في إدارة خوادمك الخاصة، فهو يوفّر لك خوادم PHP 7+ مع كل ما تحتاجه لتشغيل تطبيقات Laravel حديثة وقويّة مع Horizon.
الوسوم
يوفر لك Horizon إمكانيّة تعيين وسوم على الوظائف (jobs)، بما في ذلك البريد، وبث الأحداث والإشعارات ومستمعي الأحداث في الطابور. في الواقع، سيضع Horizon بشكل تلقائي وذكي الوسوم لمعظم الوظائف بالاعتماد على نماذج Eloquent المرتبطة بالوظيفة. فعلى سبيل المثال، ألقِ نظرة على المهمة التالية:
<?php
namespace App\Jobs;
use App\Video;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class RenderVideo implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* هذا مثيل الفيديو.
*
* @var \App\Video
*/
public $video;
/**
* إنشاء مثيل مهمة جديد.
*
* @param \App\Video $video
* @return void
*/
public function __construct(Video $video)
{
$this->video = $video;
}
/**
* تنفيذ المهمة.
*
* @return void
*/
public function handle()
{
//
}
}
إذا وُضعت وظيفة في الطابور مع نسخة App\Video
التي تملك معرّف يساوي 1، فستحصل بشكل تلقائي على الوسم App\Video:1
. وهذا لأن Horizon سيدرس خصائص الوظيفة لأي نموذج Eloquent
، فإذا وُجد نموذج Eloquent
، سيضع Horizon الوسم بذكاء في الوظيفة باستخدام اسم صنف النموذج والمفتاح الرئيسي.
$video = App\Video::find(1);
App\Jobs\RenderVideo::dispatch($video);
وضع الوسوم يدويًا
إذا كنت ترغب في تحديد الوسوم لأحد الكائنات التي يمكن أن تضعها على الطابور، فيمكنك تحديد التابع tags
في الصنف:
class RenderVideo implements ShouldQueue
{
/**
* للحصول على الوسوم المستندة إلى المهمة
*
* @return array
*/
public function tags()
{
return ['render', 'video:'.$this->video->id];
}
}
الإشعارات
ملاحظة: قبل استخدام الإشعارات، يجب عليك إضافة حزمة guzzlehttp/guzzle Composer إلى مشروعك، وعند تهيئة Horizon لإرسال إشعارات SMS، يجب عليك في هذه الحالة مراجعة المتطلبات الأساسيّة لبرنامج تشغيل الإشعارات Nexmo.
إذا كنت ترغب في أن تُعلم عندما يكون وقت انتظار إحدى الطوابير طويل، فيمكنك استخدام توابع Horizon::routeMailNotificationsTo
و Horizon::routeSlackNotificationsTo
وHorizon::routeSmsNotificationsTo
، ويمكنك استدعاء هذه التوابع من مقدّم الخدمة AppServiceProvider
الخاص بك:
Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
Horizon::routeSmsNotificationsTo('15556667777');
ضبط الإشعارات للحدود القصوى لوقت الانتظار
يمكنك وضع عدد الثواني التي تُعتبر "وقت انتظار طويل" من خلال ملف الضبط config/horizon.php
، ويتيح لك خيار الضبط waits
داخل هذا الملف بالتحكم بأقصى حد للانتظار لكل تجميعة اتصال/طابور:
'waits' => [
'redis:default' => 60,
],
المقاييس Metrics
يحتوي Horizon على لوحة تحكم بالمقاييس التي توفر المعلومات عن وظيفتك ووقت انتظار الطابور والإنتاجيّة (throughput). ولتعبئة لوحة التحكم، يجب ضبط أمر Artisan snapshot
للعمل كل خمسة دقائق عبر مجدول التطبيق الخاص بك:
/**
* تعريف أمر التطبيق schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('horizon:snapshot')->everyFiveMinutes();
}