بهینه سازی شبکه

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

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

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

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

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

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

  • HTTP/S
  • API های گوگل

درخواست های 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 تبدیل شود، برمی گرداند.

دسترسی به API های گوگل

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

ایجاد یک شی کلاینت Pub/Sub منجر به یک اتصال و دو درخواست DNS در هر فراخوانی می شود. برای جلوگیری از اتصالات غیر ضروری و پرس و جوهای DNS، شیء مشتری 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 به طور خودکار در زمان اجرا پایتون 3.7 تنظیم می شود. در زمان اجراهای بعدی، مطمئن شوید که آن را در استقرار تابع مشخص کنید. پیکربندی متغیرهای محیط را ببینید.

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

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

پس از 10 دقیقه زمان بیکار برای درخواست های تابع شما به شبکه VPC یک بازه زمانی وجود دارد. برای درخواست از عملکرد شما به اینترنت، پس از 20 دقیقه زمان بیکار، یک بازه زمانی وجود دارد.

اتصال خروجی بازنشانی می شود

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

تست بارگذاری عملکرد شما

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

$ artillery quick -d 300 -r 30 URL

این دستور URL داده شده را در 30 QPS به مدت 300 ثانیه واکشی می کند.

پس از انجام آزمایش، میزان استفاده از سهمیه اتصال خود را در صفحه سهمیه Cloud Functions API در Cloud Console بررسی کنید. اگر استفاده به طور مداوم حدود 30 (یا چند برابر آن) است، در هر فراخوانی یک (یا چند) اتصال برقرار می کنید. پس از بهینه سازی کد خود، باید مشاهده کنید که چند اتصال (10-30) فقط در ابتدای آزمایش رخ می دهد.

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