אופטימיזציה של רשתות

הפשטות של 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 ) ומחזיר את טקסט התגובה, או כל סט של ערכים שניתן להפוך לאובייקט Response באמצעות make_response .

גישה לממשקי API של Google

הדוגמה שלהלן משתמשת ב- 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 ) ומחזיר את טקסט התגובה, או כל סט של ערכים שניתן להפוך לאובייקט Response באמצעות make_response .

משתנה הסביבה GCP_PROJECT מוגדר אוטומטית בזמן הריצה של Python 3.7. בזמני ריצה מאוחרים יותר, הקפד לציין זאת בפריסת הפונקציה. ראה הגדרת משתני סביבה .

בדיקת עומס הפונקציה שלך

כדי למדוד כמה חיבורים הפונקציה שלך מבצעת בממוצע, פשוט פרוס אותה כפונקציית HTTP והשתמש במסגרת לבדיקת ביצועים כדי להפעיל אותה ב-QPS מסוים. בחירה אפשרית אחת היא ארטילריה , אותה תוכל להפעיל בשורה אחת:

$ artillery quick -d 300 -r 30 URL

פקודה זו מביאה את כתובת האתר הנתונה ב-30 QPS למשך 300 שניות.

לאחר ביצוע הבדיקה, בדוק את השימוש במכסת החיבור שלך בדף מכסת ה-API של Cloud Functions ב-Cloud Console. אם השימוש הוא בעקביות סביב 30 (או המרובות שלו), אתה יוצר קשר אחד (או כמה) בכל הזמנה. לאחר שתבצע אופטימיזציה של הקוד שלך, אתה אמור לראות כמה (10-30) חיבורים מתרחשים רק בתחילת הבדיקה.

אתה יכול גם להשוות את עלות המעבד לפני ואחרי האופטימיזציה על חלקת מכסת המעבד באותו עמוד.