درحال بهینه‌سازی شبکه

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

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

  • زمان واحد پردازش مرکزی صرف‌شده برای ایجاد اتصالات خروجی جدید در هر فراخوانی تابع را کاهش دهید.
  • احتمال تمام شدن سهمیه اتصال یا ساناد را کاهش دهید.

حفظ اتصالات پایدار

این بخش نمونه‌هایی از نحوه حفظ اتصالات پایدار در یک تابع را ارائه می‌دهد. انجام ندادن این کار می‌تواند منجر به اتمام سریع سهمیه اتصال شود.

سناریوهای زیر در این بخش پوشش داده شده است:

  • HTTP/S
  • Google APIs

درخواست‌های HTTP/S

تکه کد بهینه‌سازی‌شده زیر نشان می‌دهد که چگونه به‌جای ایجاد اتصال جدید در هر فراخوانی تابع، اتصالات پایدار را حفظ کنید:

Node.js

const http = require('http');
const functions = require('firebase-functions');

// Setting the `keepAlive` option to `true` keeps
// connections open between function invocations
const agent = new http.Agent({keepAlive: true});

exports.function = functions.https.onRequest((request, response) => {
    req = http.request({
        host: '',
        port: 80,
        path: '',
        method: 'GET',
        agent: agent, // Holds the connection open after the first invocation
    }, res => {
        let rawData = '';
        res.setEncoding('utf8');
        res.on('data', chunk => { rawData += chunk; });
        res.on('end', () => {
            response.status(200).send(`Data: ${rawData}`);
        });
    });
    req.on('error', e => {
        response.status(500).send(`Error: ${e.message}`);
    });
    req.end();
});

پایتون

from firebase_functions import https_fn
import requests

# Create a global HTTP session (which provides connection pooling)
session = requests.Session()

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

    # The URL to send the request to
    url = "http://example.com"

    # Process the request
    response = session.get(url)
    response.raise_for_status()
    return https_fn.Response("Success!")
    

این تابع HTTP از استخر اتصال برای ایجاد درخواست‌های HTTP استفاده می‌کند. این تابع یک شیء درخواست (flask.Request) می‌گیرد و نوشتار پاسخ یا هر مجموعه مقادیر را که بااستفاده از make_response می‌توان آن‌ها را به شیء Response تبدیل کرد برمی‌گرداند.

دسترسی به Google APIs

مثال زیر از Cloud Pub/Sub استفاده می‌کند، اما این رویکرد برای کتابخانه‌های مشتری دیگر نیز کار می‌کند—برای مثال، Cloud Natural Language یا Cloud Spanner. توجه داشته باشید که بهبودهای عملکرد ممکن است به پیاده‌سازی فعلی کتابخانه‌های کاربر خاص بستگی داشته باشد.

ایجاد یک شیء کارخواه Pub/Sub منجر به یک اتصال و دو پُرسمان ساناد به‌ازای هر فراخوانی می‌شود. برای جلوگیری از اتصالات و پُرسمان‌های ساناد غیرضروری، همان‌طور که در نمونه زیر نشان داده شده است، شیء کارخواه Pub/Sub را در محدوده سراسری ایجاد کنید:

node.js

const PubSub = require('@google-cloud/pubsub');
const functions = require('firebase-functions');
const pubsub = PubSub();

exports.function = functions.https.onRequest((req, res) => {
    const topic = pubsub.topic('');

    topic.publish('Test message', err => {
        if (err) {
            res.status(500).send(`Error publishing the message: ${err}`);
        } else {
            res.status(200).send('1 message published');
        }
    });
});

پایتون

import os

from firebase_functions import https_fn
from google.cloud import pubsub_v1

# from firebase_functions import https_fn
# Create a global Pub/Sub client to avoid unneeded network activity
pubsub = pubsub_v1.PublisherClient()

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

    project = os.getenv("GCP_PROJECT")
    request_json = request.get_json()

    topic_name = request_json["topic"]
    topic_path = pubsub.topic_path(project, topic_name)

    # Process the request
    data = b"Test message"
    pubsub.publish(topic_path, data=data)

    return https_fn.Response("1 message published")
    

این تابع HTTP از نمونه کتابخانه کارخواه ذخیره‌شده در حافظه نهان استفاده می‌کند تا تعداد اتصالات موردنیاز برای هر فراخوانی تابع را کاهش دهد. درخواست شیء (flask.Request) را می‌گیرد و نوشتار پاسخ یا هر مجموعه مقداری را که بااستفاده از make_response می‌تواند به شیء Response تبدیل شود برمی‌گرداند.

متغیر محیطی GCP_PROJECT به‌طور خودکار در زمان اجرای Python 3.7 تنظیم می‌شود. در زمان‌های اجرای بعدی، حتماً آن را در استقرار تابع مشخص کنید. پیکربندی متغیرهای محیط را ببینید.

اتصال‌های خروجی

مهلت زمانی درخواست خروجی

پس‌از ۱۰ دقیقه زمان بیکاری برای درخواست‌های تابع شما به شبکه VPC، زمان اتمام وجود دارد. برای درخواست‌های تابع شما به اینترنت، پس‌از ۲۰ دقیقه زمان بیکاری، مهلت زمانی وجود دارد.

بازنشانی‌های اتصال خروجی

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

آزمایش بار کردن کارکرد

برای اندازه‌گیری اینکه تابع شما به‌طور میانگین چند اتصال انجام می‌دهد، آن را به‌عنوان تابع HTTP پیاده‌سازی کنید و از چارچوب آزمایش عملکرد برای فراخوانی آن در QPS معین استفاده کنید. یکی از انتخاب‌های ممکن توپخانه است که می‌توانید با یک خط آن را فراخوانی کنید:

$ artillery quick -d 300 -r 30 URL

این فرمان نشانی وب داده‌شده را با ۳۰ پرسش در ثانیه به‌مدت ۳۰۰ ثانیه واکشی می‌کند.

پس‌از انجام آزمایش، استفاده از سهمیه اتصال خود را در Cloud Functions صفحه سهمیه API در کنسول Google Cloud بررسی کنید. اگر مصرف به‌طور مداوم حدود ۳۰ (یا مضربی از آن) باشد، در هر فراخوانی یک (یا چند) اتصال برقرار می‌کنید. پس‌از بهینه‌سازی کد، باید ببینید که چند اتصال (۱۰ تا ۳۰) فقط در ابتدای آزمایش رخ می‌دهد.

همچنین می‌توانید هزینه واحد پردازش مرکزی را قبل و بعداز بهینه‌سازی در طرح سهمیه واحد پردازش مرکزی در همان صفحه مقایسه کنید.