تقديم الخادم في بيئة بدون خادم

مؤلف المادة ، التي ننشر ترجمتها ، هو أحد مؤسسي مشروع Webiny - CMS بدون خادم يستند إلى React و GraphQL و Node.js. يقول إن دعم نظام سحابي متعدد الملقمات بدون خادم هو عمل له مهام محددة. تم بالفعل كتابة العديد من المقالات التي تناقش فيها التقنيات القياسية لتحسين مشاريع الويب. من بينها تقديم الخادم ، واستخدام تقنيات تطوير تطبيقات الويب المتقدمة ، وطرق مختلفة لتحسين تصميم التطبيقات ، وأكثر من ذلك بكثير. هذه المقالة ، من جهة ، تشبه المقالات الأخرى ، ومن ناحية أخرى ، فهي تختلف عنهم. الحقيقة هي أنها مكرسة لتحسين المشاريع التي تعمل في بيئة بدون خادم.



تدريب


من أجل إجراء قياسات من شأنها المساعدة في تحديد مشاكل المشروع ، سنستخدم webpagetest.org . بمساعدة هذا المورد ، سنقوم بالوفاء بالطلبات وجمع المعلومات حول وقت تنفيذ العمليات المختلفة. سيسمح لنا ذلك بفهم ما يراه المستخدمون ويشعرون به بشكل أفضل عند العمل مع المشروع.

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

مؤشرات تعكس ميزات تحميل الموقع - تحديد المشاكل


نلقي نظرة على الرسم البياني التالي.


تحليل المؤشرات القديمة والجديدة لمشروع الويب

هنا ، يمكن التعرف على المؤشر الأكثر أهمية على أنه "وقت البدء في التجسيد" - الوقت قبل بدء التقديم. إذا نظرت عن كثب إلى هذا المؤشر ، يمكنك أن ترى أنه فقط من أجل البدء في عرض الصفحة ، في الإصدار القديم من المشروع ، استغرق الأمر حوالي ثانيتين. يكمن سبب ذلك في جوهر تطبيق صفحة واحدة (SPA). لعرض صفحة مثل هذا التطبيق على الشاشة ، تحتاج أولاً إلى تحميل حزمة JS الضخمة (يتم وضع علامة على هذه المرحلة من تحميل الصفحة في الشكل التالي كـ 1). ثم تحتاج هذه الحزمة إلى المعالجة في الخيط الرئيسي (2). وبعد ذلك فقط ، يمكن أن يظهر شيء ما في نافذة المتصفح.


(1) قم بتنزيل حزمة JS. (2) في انتظار معالجة الحزمة في الموضوع الرئيسي

ومع ذلك ، هذا ليس سوى جزء من الصورة. بعد أن يقوم مؤشر الترابط الرئيسي بمعالجة حزمة JS ، فإنه يقدم عدة طلبات إلى Gateway API. في هذه المرحلة من معالجة الصفحة ، يرى المستخدم مؤشر تحميل بالتناوب. مشهد ليس هو الأكثر متعة. ومع ذلك ، لم ير المستخدم بعد أي محتوى الصفحة. فيما يلي القصة المصورة لعملية تحميل الصفحة.


تحميل الصفحة

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


تحميل الصفحة

إذا تم استضافة المشروع على VPS منتظم ، فسيكون الوقت اللازم لإكمال طلبات واجهة برمجة التطبيقات هذه متوقعًا في الغالب. ومع ذلك ، تتأثر المشاريع التي تعمل في بيئة بدون خادم بمشكلة "البداية الباردة" الشهيرة. في حالة منصة Webiny السحابية ، فإن الوضع أسوأ. ميزات AWS Lambda جزء من VPC (Virtual Private Cloud). هذا يعني أنه في كل مثيل جديد لهذه الوظيفة ، تحتاج إلى تهيئة ENI (واجهة شبكة مرنة ، واجهة شبكة مرنة). هذا يزيد بشكل كبير من وقت البدء البارد للوظائف.

إليك بعض الجداول الزمنية لتحميل ميزات AWS Lambda داخل VPCs وخارج VPCs.


تحليل حمل وظيفة AWS Lambda داخل VPC وخارج VPC (الصورة مأخوذة من هنا )

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

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

مهام التحسين


بناءً على التحليل الوارد أعلاه ، قمنا بصياغة العديد من المهام التي نحتاجها لحلها لتحسين المشروع. ها هم:

  • تحسين سرعة تنفيذ طلبات واجهة برمجة التطبيقات أو تقليل عدد طلبات واجهة برمجة التطبيقات التي تحظر العرض.
  • تقليل حجم حزمة JS أو تحويل هذه الحزمة إلى موارد غير ضرورية لإخراج الصفحة.
  • فتح الخيط الرئيسي.

نهج المشكلة


فيما يلي بعض الطرق لحل المشكلات التي نظرنا فيها:

  1. تحسين الكود بهدف تسريع تنفيذه. هذا النهج يتطلب الكثير من الجهد ، له تكلفة عالية. الفوائد التي يمكن الحصول عليها نتيجة لهذا التحسين مشكوك فيها.
  2. زيادة مقدار ذاكرة الوصول العشوائي المتاحة لميزات AWS Lambda. من السهل القيام به ، تكلفة مثل هذا الحل في مكان ما بين المتوسطة والعالية. يمكن توقع آثار إيجابية صغيرة فقط من تطبيق هذا الحل.
  3. استخدام طريقة أخرى لحل المشكلة. صحيح ، في تلك اللحظة لم نكن نعرف بعد ما هي هذه الطريقة.

في النهاية ، اخترنا العنصر الثالث في هذه القائمة. لقد فكرنا في هذا: "ماذا لو لم نكن نحتاج مطلقًا إلى مكالمات API؟ ماذا لو استطعنا الاستغناء عن حزمة JS على الإطلاق؟ هذا سيتيح لنا حل جميع مشاكل المشروع. "


كانت الفكرة الأولى التي وجدناها مثيرة للاهتمام هي إنشاء لقطة HTML للصفحة المقدمة ومشاركة اللقطة مع المستخدمين.

محاولة فاشلة


Webiny Cloud هي بنية تحتية بدون خادم تستند إلى AWS Lambda تدعم مواقع Webiny. يمكن لنظامنا الكشف عن السير. عندما يتبين أن الطلب قد تم إكماله بواسطة الروبوت ، تتم إعادة توجيه هذا الطلب إلى مثيل Puppeteer ، والذي يعرض الصفحة باستخدام Chrome دون واجهة مستخدم. يتم إرسال شفرة HTML الجاهزة للصفحة إلى الروبوت. تم ذلك بشكل رئيسي لأسباب تحسين محركات البحث ، نظرًا لحقيقة أن العديد من برامج الروبوت لا تعرف كيفية تنفيذ JavaScript. قررنا استخدام نفس الطريقة لإعداد الصفحات المخصصة للمستخدمين العاديين.


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

تقديم SSR


يتمثل الجانب القوي من تقديم جانب الخادم (SSR) في أن جميع طلبات واجهة برمجة التطبيقات يتم تنفيذها داخل الشبكة المحلية. نظرًا لأنه يتم معالجتها بواسطة نظام أو وظيفة معينة تعمل داخل VPC ، فإن التأخيرات التي تحدث عند تنفيذ الطلبات من المستعرض إلى الواجهة الخلفية للمورد غير معتادة. رغم أنه في هذا السيناريو ، تبقى مشكلة "البداية الباردة".

ميزة إضافية لاستخدام SSR هي أننا نمنح العميل إصدار HTML من الصفحة ، عند العمل به ، وبعد تحميل ملفات JS ، لا تواجه مكونات React مشكلات في التثبيت.

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

بشكل عام ، يمكننا القول أن تقديم الخادم ، على ما يبدو ، كان ينبغي أن يحل معظم مشاكلنا.

هذه هي الطريقة التي يبحث بها تحليل الموقع بعد تطبيق العرض من جانب الخادم.


مقاييس الموقع بعد تطبيق تقديم الخادم

الآن لا يتم تنفيذ طلبات API ، ويمكن رؤية الصفحة قبل تحميل حزمة JS الكبيرة. ولكن إذا نظرت عن كثب إلى الطلب الأول ، يمكنك أن ترى أن الأمر يستغرق ثانيتين تقريبًا للحصول على وثيقة من الخادم. دعنا نتحدث عن ذلك.

مشكلة مع TTFB


هنا نناقش مقياس TTFB (الوقت اللازم للبايت الأول ، الوقت اللازم للبايت الأول). هنا تفاصيل الطلب الأول.


تفاصيل الطلب الأول

لمعالجة هذا الطلب الأول ، نحتاج إلى القيام بما يلي: قم بتشغيل خادم Node.js ، وأداء تجسيد الخادم ، وتقديم طلبات واجهة برمجة التطبيقات ، وتنفيذ شفرة JS ، ثم إعادة النتيجة النهائية إلى العميل. المشكلة هنا هي أن كل هذا ، في المتوسط ​​، يستغرق 1-2 ثواني.

يجب أن يقوم خادمنا ، الذي ينفذ عرض الخادم ، بكل هذا العمل ، وبعد ذلك فقط سيكون قادرًا على إرسال البايت الأول من الاستجابة إلى العميل. هذا يؤدي إلى حقيقة أن المتصفح لديه وقت طويل للغاية لانتظار بداية الرد على الطلب. نتيجة لذلك ، اتضح الآن أنه بالنسبة لإخراج الصفحة ، فأنت بحاجة إلى إنتاج نفس مقدار العمل تقريبًا كما كان من قبل. الفرق الوحيد هو أن هذا العمل لا يتم تنفيذه من جانب العميل ، ولكن على الخادم ، في عملية تقديم الخادم.

هنا قد يكون لديك سؤال حول كلمة "الخادم". لقد كنا نتحدث عن نظام serverless طوال هذا الوقت. من أين جاء هذا "الخادم"؟ حاولنا ، بالطبع ، تقديم عرض الخادم في وظائف AWS Lambda. لكن اتضح أن هذه عملية مستهلكة للغاية للموارد (على وجه الخصوص ، كان من الضروري زيادة مقدار الذاكرة كثيرًا من أجل الحصول على مزيد من موارد المعالج). بالإضافة إلى ذلك ، تمت إضافة مشكلة "البداية الباردة" ، التي ذكرناها بالفعل ، هنا أيضًا. كنتيجة لذلك ، كان الحل المثالي هو استخدام خادم Node.js الذي سيقوم بتحميل مواد الموقع والمشاركة في تقديمها من جانب الخادم.

دعنا نعود إلى عواقب استخدام التقديم من جانب الخادم. ألق نظرة على لوحة العمل التالية. من السهل أن نرى أنه لا يختلف بشكل خاص عن ما تم الحصول عليه في دراسة المشروع ، والتي تم تقديمها على العميل.


يتم تحميل الصفحة عند استخدام العرض من جانب الخادم

يجبر المستخدم على النظر إلى صفحة فارغة لمدة 2.5 ثانية. هذا محزن.

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

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

التخزين المؤقت خادم تقديم النتائج


بعد زيارة المستخدم لموقع Webiny ، نتحقق أولاً من ذاكرة التخزين المؤقت المركزية لـ Redis لمعرفة ما إذا كانت هناك لقطة HTML للصفحة. إذا كان الأمر كذلك ، فنحن نقدم للمستخدم صفحة من ذاكرة التخزين المؤقت. في المتوسط ​​، خفض هذا TTFB إلى 200-400 مللي ثانية. بعد إدخال ذاكرة التخزين المؤقت ، بدأنا نلاحظ حدوث تحسن كبير في أداء المشروع.


يتم تحميل الصفحة عند استخدام التقديم من جانب الخادم وذاكرة التخزين المؤقت

حتى المستخدم الذي يزور الموقع لأول مرة ، يرى محتويات الصفحة في أقل من ثانية.

دعنا ننظر إلى كيف يبدو مخطط الشلال الآن.


مقاييس الموقع بعد تطبيق التقديم من جانب الخادم والتخزين المؤقت

يشير الخط الأحمر إلى ختم زمني قدره 800 مللي ثانية. هذا هو المكان الذي يتم فيه تحميل محتوى الصفحة بالكامل. بالإضافة إلى ذلك ، هنا يمكنك أن ترى أن حزم JS يتم تحميلها في حوالي 1.3 ثانية. لكن هذا لا يؤثر على الوقت الذي يحتاج فيه المستخدم لرؤية الصفحة. في الوقت نفسه ، لا تحتاج إلى إجراء مكالمات API وتحميل مؤشر الترابط الرئيسي لعرض الصفحة.

انتبه إلى حقيقة أن المؤشرات المؤقتة المتعلقة بتحميل حزمة JS وتنفيذ طلبات واجهة برمجة التطبيقات وتنفيذ العمليات في سلسلة الرسائل الرئيسية لا تزال تلعب دورًا مهمًا في إعداد الصفحة للعمل. مطلوب استثمار الوقت والموارد من أجل أن تصبح الصفحة "تفاعلية". ولكن هذا لا يلعب أي دور ، أولاً ، بالنسبة لمحركات البحث الآلية ، وثانياً ، في خلق شعور "التحميل السريع للصفحة" بين المستخدمين.

لنفترض أن الصفحة "ديناميكية". على سبيل المثال ، يعرض رابطًا في الرأس للوصول إلى حساب المستخدم في حالة تسجيل دخول المستخدم الذي يشاهد الصفحة. بعد التقديم من جانب الخادم ، سيتم إرسال صفحة الأغراض العامة إلى المتصفح. هذا - واحد يتم عرضه للمستخدمين الذين لم يقوموا بتسجيل الدخول. سيتم تغيير عنوان هذه الصفحة ، مما يعكس حقيقة تسجيل دخول المستخدم ، فقط بعد تحميل حزمة JS وإجراء مكالمات API. نحن هنا نتعامل مع مؤشر TTI (حان وقت التفاعل ، وقت التفاعل الأول).

بعد بضعة أسابيع ، وجدنا أن الخادم الوكيل لدينا لا يغلق الاتصال بالعميل عند الحاجة ، في حالة بدء تقديم الخادم كعملية خلفية. أدى التصحيح حرفيًا سطر واحد من التعليمات البرمجية إلى حقيقة أن مؤشر TTFB تم تخفيضه إلى مستوى 50-90 مللي ثانية. نتيجة لذلك ، بدأ الموقع الآن في العرض في المتصفح بعد حوالي 600 مللي ثانية.

ومع ذلك ، واجهنا مشكلة أخرى ...

مشكلة إبطال ذاكرة التخزين المؤقت


"في علوم الكمبيوتر ، هناك شيئان معقدان فقط: إبطال ذاكرة التخزين المؤقت وتسمية الكيان."
فيل كارلتون

يعد إبطال ذاكرة التخزين المؤقت مهمة صعبة للغاية. كيفية حلها؟ أولاً ، يمكنك تحديث ذاكرة التخزين المؤقت غالبًا عن طريق تعيين وقت تخزين قصير جدًا للكائنات المخزنة مؤقتًا (TTL ، ووقت البقاء ، وعمر الحياة). سيؤدي هذا في بعض الأحيان إلى تحميل الصفحات ببطء أكثر من المعتاد. ثانياً ، يمكنك إنشاء آلية لإبطال ذاكرة التخزين المؤقت بناءً على أحداث معينة.

في حالتنا ، تم حل هذه المشكلة باستخدام TTL صغير جدًا لمدة 30 ثانية. لكننا أدركنا أيضًا إمكانية تزويد العملاء ببيانات قديمة من ذاكرة التخزين المؤقت. في الوقت الذي يتلقى فيه العملاء مثل هذه البيانات ، يتم تحديث ذاكرة التخزين المؤقت في الخلفية. بفضل هذا ، تخلصنا من المشاكل ، مثل التأخير و "البداية الباردة" ، والتي تعتبر نموذجية لوظائف AWS Lambda.

إليك كيف تعمل. مستخدم يزور موقع Webiny. نحن نتحقق من ذاكرة التخزين المؤقت لـ HTML. إذا كانت هناك لقطة شاشة للصفحة ، فنحن نقدمها للمستخدم. يمكن أن يكون عمر الصورة بضعة أيام. بتمرير هذه اللقطة القديمة إلى المستخدم في بضع مئات من المللي ثانية ، نطلق في وقت واحد مهمة إنشاء لقطة جديدة وتحديث ذاكرة التخزين المؤقت. عادة ما يستغرق إكمال هذه المهمة بضع ثوانٍ ، لأننا أنشأنا آلية بفضلنا دائمًا لدينا عدد معين من وظائف AWS Lambda التي تعمل بالفعل وجاهزة للعمل. لذلك ، لا يتعين علينا ، أثناء إنشاء صور جديدة ، قضاء بعض الوقت في البداية الباردة للوظائف.

نتيجة لذلك ، نقوم دائمًا بإرجاع الصفحات من ذاكرة التخزين المؤقت إلى العملاء ، وعندما يصل عمر البيانات المخزنة مؤقتًا إلى 30 ثانية ، يتم تحديث محتويات ذاكرة التخزين المؤقت.

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

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

ما زلنا نبحث عن طرق لتحسين نظام التخزين المؤقت لمشروعنا. ولكن حتى الآن ، كان التركيز منصباً على حل مشكلات الأداء الحالية. نعتقد أننا قمنا بعمل جيد من حيث حل هذه المشاكل.

النتائج


في البداية ، استخدمنا التقديم من جانب العميل. ثم ، في المتوسط ​​، يمكن للمستخدم رؤية الصفحة في 3.3 ثانية. الآن ، انخفض هذا الرقم إلى حوالي 600 مللي ثانية. من المهم أيضًا الاستغناء عن مؤشر التنزيل الآن.

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

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

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

أعزائي القراء! هل تستخدم تقنيات التخزين المؤقت وتقديم الخادم لتحسين مشاريعك؟

Source: https://habr.com/ru/post/ar459306/


All Articles