نصائح

يصف هذا المستند أفضل الممارسات للتصميم والتنفيذ والاختبار ونشر وظائف Cloud.

الإجابات الصحيحة

يصف هذا القسم أفضل الممارسات العامة لتصميم وتنفيذ وظائف السحابة الإلكترونية:

كتابة الدوال غير الثابتة

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

عدم بدء الأنشطة في الخلفية

يشير النشاط في الخلفية إلى أيّ نشاط يحدث بعد إنهاء الوظيفة. ينتهي استدعاء الدالة عند رجوع الدالة أو إرسال إشارات اكتمال، مثل استدعاء الوسيطة callback في Node.js المستندة إلى حدث الأخرى. لا يمكن لأي رمز يتم تشغيله بعد الإنهاء السلس الوصول إلى وحدة المعالجة المركزية لن يحقق أي تقدم.

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

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

حذف الملفات المؤقتة دائمًا

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

يمكنك مشاهدة الذاكرة المستخدمة بواسطة دالة فردية من خلال تحديدها في قائمة الدوال في وحدة تحكّم Google Cloud Platform واختيار مخطط استخدام الذاكرة.

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

يمكنك تقليل متطلبات الذاكرة عند معالجة الملفات الكبيرة باستخدام الممرات. على سبيل المثال، يمكنك معالجة ملف على Cloud Storage من خلال إنشاء ساحة مشاركات للقراءة. وتمريرها من خلال عملية تستند إلى البث وكتابة تدفق المخرجات مباشرةً إلى Cloud Storage.

إطار الدوال

عند نشر دالة، تتم إضافة إطار عمل الدوال تلقائيًا التبعية، باستخدام إصدارها الحالي. للتأكد من أن نفس التبعيات مثبّتة باستمرار عبر بيئات مختلفة، فإننا نوصي يمكنك تثبيت الدالة في إصدار معين من إطار عمل الدوال.

لإجراء ذلك، عليك تضمين الإصدار المفضّل لديك في ملف القفل ذي الصلة. (على سبيل المثال، package-lock.json للغة Node.js أو requirements.txt للغة Python).

الأدوات

يقدم هذا القسم إرشادات حول كيفية استخدام الأدوات لتنفيذ الأدوات واختبارها التفاعل مع دوال السحابة.

تنمية محلية

يستغرق نشر الدوال بعض الوقت، لذلك غالبًا ما يكون اختبار الرمز أسرع. لدالتك محليًا.

يمكن لمطوّري البرامج في Firebase استخدام محاكي وظائف السحابة الإلكترونية لواجهة سطر الأوامر في Firebase

استخدام Sendgrid لإرسال الرسائل الإلكترونية

لا تسمح وظائف السحابة الإلكترونية بالاتصالات الصادرة على المنفذ 25، لذا لا يمكنك إجراء اتصالات غير آمنة بخادم SMTP. الطريقة الموصى بها لإرسال الرسائل الإلكترونية هي استخدام SendGrid. تتوفر خيارات أخرى لإرسال رسالة إلكترونية في إرسال رسائل إلكترونية من مثيل البرنامج التعليمي حول Google Compute Engine

الأداء

يصف هذا القسم أفضل الممارسات لتحسين الأداء.

استخدام التبعيات بحكمة

بما أنّ الدوال عديمة الحالة، غالبًا ما يتم إعداد بيئة التنفيذ من البداية (أثناء ما يُعرف باسم البداية الباردة). عندما تحدث البداية على البارد، تقييم السياق العام للدالة.

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

استخدام المتغيّرات العمومية لإعادة استخدام العناصر في الاستدعاءات المستقبلية

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

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

Node.js

console.log('Global scope');
const perInstance = heavyComputation();
const functions = require('firebase-functions');

exports.function = functions.https.onRequest((req, res) => {
  console.log('Function invocation');
  const perFunction = lightweightComputation();

  res.send(`Per instance: ${perInstance}, per function: ${perFunction}`);
});

Python

import time

from firebase_functions import https_fn

# Placeholder
def heavy_computation():
  return time.time()

# Placeholder
def light_computation():
  return time.time()

# Global (instance-wide) scope
# This computation runs at instance cold-start
instance_var = heavy_computation()

@https_fn.on_request()
def scope_demo(request):

  # Per-function scope
  # This computation runs every time this function is called
  function_var = light_computation()
  return https_fn.Response(f"Instance: {instance_var}; function: {function_var}")
  

تستخدم دالة HTTP هذه كائن طلب (flask.Request)، وتعرض نص الاستجابة أو أي مجموعة من القيم التي يمكن تحويلها إلى عنصر واحد (Response) يستخدم make_response

من المهم بشكل خاص تخزين اتصالات الشبكة ومراجع المكتبة وواجهة برمجة التطبيقات (API) في النطاق العمومي. راجع تحسين الشبكات للحصول على أمثلة.

إجراء الإعداد الكسول للمتغيّرات العمومية

في حال إعداد المتغيرات على نطاق عمومي، سيتم دائمًا يتم تنفيذها من خلال استدعاء التشغيل على البارد، مما يزيد من وقت استجابة وظيفتك. في بعض الحالات، يؤدي ذلك إلى حدوث مهلات متقطّعة للخدمات التي يتم طلبها. إذا لم يتم التعامل معها بشكل مناسب ضمن مجموعة try من catch. في حال حذف لا تُستخدَم بعض العناصر في جميع مسارات الرموز البرمجية، لذا ننصحك بإعدادها بشكل كسول عند الطلب:

Node.js

const functions = require('firebase-functions');
let myCostlyVariable;

exports.function = functions.https.onRequest((req, res) => {
  doUsualWork();
  if(unlikelyCondition()){
      myCostlyVariable = myCostlyVariable || buildCostlyVariable();
  }
  res.status(200).send('OK');
});

Python

from firebase_functions import https_fn

# Always initialized (at cold-start)
non_lazy_global = file_wide_computation()

# Declared at cold-start, but only initialized if/when the function executes
lazy_global = None

@https_fn.on_request()
def lazy_globals(request):

  global lazy_global, non_lazy_global

  # This value is initialized only if (and when) the function is called
  if not lazy_global:
      lazy_global = function_specific_computation()

  return https_fn.Response(f"Lazy: {lazy_global}, non-lazy: {non_lazy_global}.")
  

تستخدم دالة HTTP هذه عبارات عمومية تم إعدادها ببطء. يتطلب كائن طلب (flask.Request)، وتعرض نص الاستجابة أو أي مجموعة من القيم يمكن تحويلها إلى كائن Response باستخدام make_response

هذا مهم بشكل خاص إذا قمت بتعريف عدة دوال في ملف واحد، بينما تستخدم الدوال المختلفة متغيرات مختلفة. ما لم تستخدم طريقة التهيئة، فقد تُهدر الموارد على المتغيرات التي تم إعدادها ولكن لم يتم استخدامها مطلقًا.

عليك تقليل عمليات التشغيل على البارد من خلال ضبط حد أدنى لعدد النُسخ الافتراضية.

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

عرض التحكّم في سلوك التوسيع للحصول على مزيد من المعلومات حول خيارات بيئة التشغيل هذه.

مراجع إضافية

تعرَّف على مزيد من المعلومات حول تحسين الأداء في صفحة "أداء السحابة الإلكترونية من Google". Versa 3 فيديو وقت التشغيل البارد في دوال Cloud