تحسين الشبكات

تتيح لك بساطة دوال السحابة الإلكترونية تطوير الرموز البرمجية وتشغيلها في بيئة غير خاضعة لخادم. على نطاق معتدل، تكون تكلفة تشغيل الدوال منخفضة، وقد لا يبدو تحسين التعليمة البرمجية أولوية عالية. ومع ذلك، كلما ازدادت وتيرة عملية النشر، تزداد أهمية تحسين الرمز البرمجي.

يصف هذا المستند كيفية تحسين الشبكات للوظائف. في ما يلي بعض فوائد تحسين الشبكات:

  • تقليل الوقت الذي يتم قضاؤه في إنشاء اتصالات صادرة جديدة في كل استدعاء دالة.
  • قلِّل احتمالية نفاد الاتصال أو حصص نظام أسماء النطاقات.

الحفاظ على علاقات دائمة

يقدّم هذا القسم أمثلة حول كيفية الحفاظ على الاتصالات المستمرة في إحدى الدوال. قد يؤدي عدم إجراء ذلك إلى استنفاد حصص الاتصال بسرعة.

يتم تناول السيناريوهات التالية في هذا القسم:

  • 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();
});

Python

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 عملية اتصال واحد وطلبي بحث لنظام أسماء النطاقات لكل استدعاء. لتجنب الاتصالات غير الضرورية وطلبات بحث نظام أسماء النطاقات، أنشئ كائن عميل النشر/الاشتراك في نطاق عام كما هو موضح في النموذج أدناه:

عقدة.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');
        }
    });
});

Python

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 واستخدام إطار عمل لاختبار الأداء لاستدعاءها في عدد معيّن من الطلبات في الثانية. أحد الخيارات المحتملة هو المدفعية، التي يمكنك استدعاؤها بسطر واحد:

$ artillery quick -d 300 -r 30 URL

يجلب هذا الأمر عنوان URL المحدَّد بسرعة 30 لقطة في الثانية لمدة 300 ثانية.

بعد إجراء الاختبار، تحقَّق من استخدام حصة الاتصال في صفحة حصة واجهة برمجة التطبيقات Cloud Functions API في Cloud Console. وإذا كان الاستخدام ثابتًا حوالي 30 (أو عدة مرات)، فأنت تنشئ اتصال واحد (أو عدة) في كل استدعاء. بعد تحسين التعليمة البرمجية، يُفترض أن ترى عدد قليل من الاتصالات (10-30) يحدث فقط في بداية الاختبار.

يمكنك أيضًا مقارنة تكلفة وحدة المعالجة المركزية قبل التحسين وبعده على مخطط حصص وحدة المعالجة المركزية في الصفحة نفسها.