Octane يسرّع Laravel بكسر افتراض تعتمد عليه
كل طلب في تطبيق Laravel عادي يبدأ من الصفر. وOctane يبقي التطبيق في الذاكرة بين الطلبات، ومن هناك تأتي السرعة ومن هناك تأتي الأعطال أيضًا.
ما يجعل PHP متسامحًا أنه ينسى. يصل طلب، فيُقلع الإطار، فيقع العمل، فتخرج العملية، فتختفي كل متغيرة أُنشئت على الطريق. تسرّب الذاكرة يدوم أجزاءً من الألف من الثانية. والخاصية الساكنة الملوَّثة ببيانات مستخدم تختفي قبل وصول المستخدم التالي.
وOctane يزيل ذلك. يُقلع التطبيق مرة ويبقى في الذاكرة، يخدم طلبًا بعد طلب في العملية نفسها. وتخطّي الإقلاع هو مصدر السرعة - وكان النسيان يحمل أشياء لم تضطر أغلب الشيفرات إلى التفكير فيها قط.
ما يكفّ عن كونه صحيحًا
الخصائص الساكنة تستمر. التخزين الساكن الذي كان لكل طلب صار مشتركًا بين كل طلب يخدمه العامل. وإن كان مفهرسًا بالمستخدم فهو تسريب بيانات.
الـ singletons تعيش أطول من الطلب الذي أنشأها. الخدمة التي تُحلّ مرة وتُسجَّل كـ singleton ستحمل ما التقطته عند أول حلّ - بما في ذلك، في أسوأ الحالات، طلبًا أو مستخدمًا مصادَقًا عليه.
المتغيرات العامة تستمر. كل ما يُكتب في متغيرة فائقة أو متغيرة عامة ينجو.
التسريبات تتراكم. مصفوفة تنمو قليلًا في كل طلب كانت مجانية. أما الآن فترتفع ذاكرة العامل حتى يعيد شيء تشغيله.
النمط الذي يعضّ فعلًا
نادرًا ما تكون مصفوفة ساكنة. بل خدمة أخذت اعتمادية كان ينبغي أن تحلّها لاحقًا:
// AppServiceProvider
$this->app->singleton(ReportBuilder::class, function ($app) {
return new ReportBuilder($app->make(Request::class));
});مسجَّلة كـ singleton، تلتقط هذه أول طلب يخدمه العامل على الإطلاق وتحتفظ به. وكل طلب لاحق يحصل على بانٍ يحمل مدخلات شخص آخر.
مع PHP العادي هذا غير ضار - تموت العملية، ويموت الـ singleton معها، ولا يلاحظ أحد العطل الكامن. أما مع Octane فهو تسريب بيانات بين المستخدمين يظهر متقطعًا ويكاد يستحيل إعادة إنتاجه من بلاغ.
والإصلاح أن تُحلّ حالة الطلب حين تلزم لا حين تُبنى الخدمة:
$this->app->singleton(ReportBuilder::class, fn () => new ReportBuilder());
// وداخل الدالة التي تحتاجها
public function build(Request $request): Report { ... }وينطبق الأمر نفسه على كل ما يلتقط المستخدم المصادَق عليه أو المستأجر الحالي أو اللغة وقت الإنشاء. وعلى منصة متعددة المستأجرين ينتقل هذا من إحراج إلى حادث خطير، لأن الحد بين المستأجرين هو بالضبط ما يُعبَر.
إيجادها قبل أن يجدها الإنتاج
اقرأ مزوّدي الخدمة أولًا. كل ربط singleton، وكل bind يحلّ إغلاقُه شيئًا بشكل
طلب، مرشَّح.
ثم ابحث عن الخصائص الساكنة التي يُكتب فيها لا التي تُقرأ فقط:
grep -rn "protected static \|private static \|public static " app/ | grep -v "function\|const"أغلبها سيكون مشروعًا. وتلك التي تحمل بيانات لا إعدادات هي القائمة التي تعمل عليها.
يوفّر Laravel خطافات لإعادة ضبط الحالة بين الطلبات، وتسجّل الحزم خطافاتها. وهي تغطي خدمات الإطار نفسه جيدًا ولا تعرف شيئًا عن خدماتك.
الجزء الذي لا يتعلق بالصحة
حتى مع معالجة الحالة، للعملية طويلة التشغيل شكل تشغيلي مختلف.
يجب مراقبة الذاكرة ساعات لا دقائق - تسريب مئة كيلوبايت لكل طلب غير مرئي في اختبار وقاتل بين عشية وضحاها. ويحتاج العمّال حدًّا أقصى لعدد الطلبات كي يُعاد تدويرهم قبل أن يتدهوروا. ويجب على النشر إعادة تشغيلهم، وهو الدرس نفسه الذي مع عمّال الطوابير: العملية طويلة العمر تحمل الشيفرة التي أقلعت بها، فلا تصلها الشيفرة الجديدة حتى يجعلها شيء تخرج.
هل يستحق؟
أحيانًا، وأقل مما توحي به المقارنات المعيارية.
الإقلاع هو ما يزيله Octane، والطلب الذي يذهب وقته في استعلام بطيء أو استدعاء طرف ثالث لا يكسب شيئًا على الإطلاق. حلّل نقطة نهاية حقيقية أولًا. إن كان إقلاع الإطار حصة معتبرة من زمن استجابتك فالمكسب حقيقي؛ وإن كانت قاعدة البيانات هي الحصة، فأصلح قاعدة البيانات.
وإن كان في التطبيق singletons تلتقط حالة طلب، فأصلحها أيًّا كان قرارك بشأن Octane. هي أعطال اليوم - فقط أن PHP يغطي عليها بصمت.
في منصة متعددة المستأجرين، المستأجر المحتجَز يتجاوز الحدّ الوحيد الذي يُباع المنتج عليه. والعملية التي تمسك بالشيفرة التي أقلعت بها هي العلة نفسها التي في عامل طوابير يشغّل إصدار الأسبوع الماضي. ولهذا على النشر أن يعيد تشغيل الاثنين.
أما إن كان الإقلاع يكلّفك شيئًا فعلًا فذلك قياس، وبه نبدأ.
