نکات & ترفندها

این سند بهترین شیوه ها را برای طراحی، پیاده سازی، آزمایش و استقرار توابع ابری توضیح می دهد.

صحت

این بخش بهترین شیوه های کلی برای طراحی و پیاده سازی توابع ابری را توضیح می دهد.

توابع idempotent را بنویسید

توابع شما باید نتیجه یکسانی داشته باشند حتی اگر چندین بار فراخوانی شوند. این به شما امکان می‌دهد اگر فراخوانی قبلی در قسمتی از کد شما شکست خورد، یک فراخوان را دوباره امتحان کنید. برای اطلاعات بیشتر، به تلاش مجدد توابع مبتنی بر رویداد مراجعه کنید.

فعالیت های پس زمینه را شروع نکنید

فعالیت پس زمینه هر چیزی است که پس از پایان عملکرد شما اتفاق می افتد. فراخوانی تابع پس از بازگشت تابع یا سیگنال‌های تکمیلی دیگر، مانند فراخوانی آرگومان callback در توابع رویداد محور Node.js به پایان می‌رسد. هر کدی که پس از خاتمه برازنده اجرا شود نمی تواند به CPU دسترسی داشته باشد و هیچ پیشرفتی نخواهد داشت.

علاوه بر این، هنگامی که فراخوانی بعدی در همان محیط اجرا می شود، فعالیت پس زمینه شما از سر گرفته می شود و در فراخوانی جدید تداخل ایجاد می کند. این ممکن است منجر به رفتارهای غیرمنتظره و خطاهایی شود که تشخیص آنها سخت است. دسترسی به شبکه پس از پایان عملکرد معمولاً منجر به تنظیم مجدد اتصالات می شود (کد خطای ECONNRESET ).

فعالیت پس‌زمینه را می‌توان با یافتن هر چیزی که بعد از خطی که فراخوانی پایان یافت ثبت شده است، در گزارش‌های مربوط به فراخوان‌های فردی شناسایی کرد. گاهی اوقات می‌توان فعالیت پس‌زمینه را عمیق‌تر در کد مدفون کرد، به‌ویژه زمانی که عملیات ناهمزمان مانند تماس‌ها یا تایمرها وجود دارد. کد خود را مرور کنید تا مطمئن شوید که تمام عملیات ناهمزمان قبل از خاتمه عملکرد به پایان می رسد.

همیشه فایل های موقت را حذف کنید

ذخیره سازی دیسک محلی در دایرکتوری موقت یک فایل سیستم در حافظه است. فایل هایی که می نویسید حافظه موجود برای عملکرد شما را مصرف می کنند و گاهی اوقات بین فراخوانی ها باقی می مانند. عدم حذف صریح این فایل ها ممکن است در نهایت منجر به خطای کمبود حافظه و متعاقبا شروع سرد شود.

با انتخاب آن در لیست توابع موجود در کنسول GCP و انتخاب نمودار استفاده از حافظه ، می توانید حافظه استفاده شده توسط یک تابع را مشاهده کنید.

سعی نکنید خارج از دایرکتوری موقت بنویسید و مطمئن شوید که از روش های مستقل از پلتفرم/OS برای ساخت مسیرهای فایل استفاده کنید.

هنگام پردازش فایل های بزرگتر با استفاده از خط لوله، می توانید نیاز به حافظه را کاهش دهید. برای مثال، می‌توانید با ایجاد یک جریان خواندن، عبور دادن آن از طریق یک فرآیند مبتنی بر جریان و نوشتن جریان خروجی مستقیماً در فضای ذخیره‌سازی ابری، یک فایل را در فضای ذخیره‌سازی ابری پردازش کنید.

چارچوب توابع

هنگامی که یک تابع را مستقر می کنید، Functions Framework به طور خودکار به عنوان یک وابستگی با استفاده از نسخه فعلی آن اضافه می شود. برای اطمینان از اینکه وابستگی های یکسان به طور مداوم در محیط های مختلف نصب می شوند، توصیه می کنیم عملکرد خود را به نسخه خاصی از Functions Framework پین کنید.

برای انجام این کار، نسخه دلخواه خود را در فایل قفل مربوطه قرار دهید (به عنوان مثال، package-lock.json برای Node.js، یا requirements.txt برای پایتون).

ابزار

این بخش دستورالعمل هایی در مورد نحوه استفاده از ابزارها برای پیاده سازی، آزمایش و تعامل با توابع ابری ارائه می دهد.

توسعه محلی

استقرار تابع کمی زمان می برد، بنابراین آزمایش کد عملکرد خود به صورت محلی اغلب سریعتر است.

توسعه دهندگان Firebase می توانند از Firebase CLI Cloud Functions Emulator استفاده کنند.

از Sendgrid برای ارسال ایمیل استفاده کنید

Cloud Functions اجازه اتصالات خروجی را در پورت 25 نمی دهد، بنابراین نمی توانید اتصالات غیر ایمن به سرور SMTP برقرار کنید. روش پیشنهادی برای ارسال ایمیل استفاده از SendGrid است. می‌توانید گزینه‌های دیگری برای ارسال ایمیل در «ارسال ایمیل از یک آموزش نمونه برای موتور محاسباتی Google» بیابید.

کارایی

این بخش بهترین روش ها برای بهینه سازی عملکرد را شرح می دهد.

از وابستگی ها عاقلانه استفاده کنید

از آنجایی که توابع بدون حالت هستند، محیط اجرا اغلب از ابتدا مقداردهی اولیه می شود (در طول چیزی که به عنوان شروع سرد شناخته می شود). هنگامی که شروع سرد رخ می دهد، زمینه کلی تابع ارزیابی می شود.

اگر توابع شما ماژول‌ها را وارد می‌کنند، زمان بارگذاری آن ماژول‌ها می‌تواند در زمان شروع سرد به تأخیر فراخوانی اضافه کند. می‌توانید با بارگیری صحیح وابستگی‌ها و بار نکردن وابستگی‌هایی که عملکرد شما از آنها استفاده نمی‌کند، این تأخیر و همچنین زمان لازم برای استقرار عملکرد خود را کاهش دهید.

از متغیرهای سراسری برای استفاده مجدد از اشیاء در فراخوانی های آینده استفاده کنید

هیچ تضمینی وجود ندارد که وضعیت یک Cloud Function برای فراخوانی های آینده حفظ شود. با این حال، Cloud Functions اغلب محیط اجرای فراخوان قبلی را بازیافت می کند. اگر متغیری را در دامنه جهانی اعلام کنید، مقدار آن را می‌توان در فراخوانی‌های بعدی بدون نیاز به محاسبه مجدد مورد استفاده قرار داد.

به این ترتیب می توانید اشیایی را که ممکن است در هر فراخوانی تابع گران باشد، ذخیره کنید. انتقال چنین اشیایی از بدنه عملکرد به محدوده جهانی ممکن است منجر به بهبود عملکرد قابل توجهی شود. مثال زیر یک شی سنگین را تنها یک بار در هر نمونه تابع ایجاد می کند و آن را در تمام فراخوانی های تابعی که به نمونه داده شده می رسد به اشتراک می گذارد:

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}`);
});

پایتون

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 ) می گیرد و متن پاسخ یا هر مجموعه ای از مقادیر را که می تواند با استفاده از make_response به یک شی 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');
});

پایتون

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 ) را می گیرد و متن پاسخ یا هر مجموعه ای از مقادیر را که می تواند با استفاده از make_response به یک شی Response تبدیل شود، برمی گرداند.

اگر چندین تابع را در یک فایل واحد تعریف کنید و توابع مختلف از متغیرهای متفاوتی استفاده کنند، این امر به ویژه مهم است. مگر اینکه از مقداردهی اولیه تنبل استفاده کنید، ممکن است منابع را بر روی متغیرهایی که مقداردهی اولیه شده اند اما هرگز استفاده نشده اند هدر دهید.

با تنظیم حداقل تعداد موارد شروع سرد را کاهش دهید

به طور پیش‌فرض، Cloud Functions تعداد نمونه‌ها را بر اساس تعداد درخواست‌های دریافتی مقیاس می‌دهد. می‌توانید این رفتار پیش‌فرض را با تنظیم حداقل تعداد نمونه‌هایی که Cloud Function باید برای ارائه درخواست‌ها آماده نگه دارد، تغییر دهید. تنظیم حداقل تعداد نمونه شروع سرد برنامه شما را کاهش می دهد. اگر برنامه شما به تأخیر حساس است، توصیه می‌کنیم حداقل تعداد نمونه‌ها را تنظیم کنید.

برای اطلاعات بیشتر در مورد این گزینه‌های زمان اجرا ، رفتار مقیاس‌بندی کنترل را ببینید.

منابع اضافی

درباره بهینه‌سازی عملکرد در ویدیوی «اطلس عملکرد ابری Google» اطلاعات بیشتری کسب کنید.