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

سادگی 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

نمونه زیر از 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 است که می‌توانید آن را با یک خط فراخوانی کنید:

$ artillery quick -d 300 -r 30 URL

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

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

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