การเพิ่มประสิทธิภาพเครือข่าย

ความเรียบง่ายของ Cloud Functions ช่วยให้คุณพัฒนาโค้ดและเรียกใช้ในสภาพแวดล้อมแบบไร้เซิร์ฟเวอร์ได้อย่างรวดเร็ว เมื่อมีขนาดปานกลาง ค่าใช้จ่ายในการเรียกใช้ฟังก์ชันจะต่ำ และการเพิ่มประสิทธิภาพโค้ดอาจดูเหมือนไม่ใช่สิ่งสำคัญอันดับแรก อย่างไรก็ตาม เมื่อการ ติดตั้งใช้งานขยายขนาด การเพิ่มประสิทธิภาพโค้ดจะมีความสำคัญมากขึ้น เรื่อยๆ

เอกสารนี้อธิบายวิธีเพิ่มประสิทธิภาพเครือข่ายสำหรับฟังก์ชัน ประโยชน์บางส่วนของการเพิ่มประสิทธิภาพเครือข่ายมีดังนี้

  • ลดเวลา CPU ที่ใช้ในการสร้างการเชื่อมต่อขาออกใหม่ในการเรียกใช้ฟังก์ชันแต่ละครั้ง
  • ลดโอกาสที่โควต้าการเชื่อมต่อหรือ DNS จะหมด

การรักษาการเชื่อมต่อที่ต่อเนื่อง

ส่วนนี้จะแสดงตัวอย่างวิธีรักษาการเชื่อมต่อที่ต่อเนื่องในฟังก์ชัน การไม่ดำเนินการดังกล่าวอาจส่งผลให้โควต้าการเชื่อมต่อหมดลงอย่างรวดเร็ว

ส่วนนี้จะครอบคลุมสถานการณ์ต่อไปนี้

  • 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

การเข้าถึง Google APIs

ตัวอย่างด้านล่างใช้ Cloud Pub/Sub แต่แนวทางนี้ ใช้ได้กับไลบรารีของไคลเอ็นต์อื่นๆ ด้วย เช่น Cloud Natural Language หรือ Cloud Spanner โปรดทราบว่าการปรับปรุงประสิทธิภาพอาจขึ้นอยู่กับการใช้งานไลบรารีของไคลเอ็นต์บางรายการในปัจจุบัน

การสร้างออบเจ็กต์ไคลเอ็นต์ Pub/Sub จะส่งผลให้มีการเชื่อมต่อ 1 รายการและการค้นหา DNS 2 รายการ ต่อการเรียกใช้ หากต้องการหลีกเลี่ยงการเชื่อมต่อและการค้นหา 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');
        }
    });
});

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 ในรันไทม์เวอร์ชันต่อๆ ไป ให้ระบุในฟังก์ชัน การติดตั้งใช้งาน ดูกำหนดค่าตัวแปร สภาพแวดล้อม

การเชื่อมต่อขาออก

คำขอขาออกหมดเวลา

คำขอจากฟังก์ชันไปยังเครือข่าย VPC จะหมดเวลาหลังจากไม่มีการใช้งานเป็นเวลา 10 นาที สำหรับคำขอจากฟังก์ชันของคุณไปยังอินเทอร์เน็ต จะมี การหมดเวลาหลังจากไม่มีการใช้งานเป็นเวลา 20 นาที

การรีเซ็ตการเชื่อมต่อขาออก

สตรีมการเชื่อมต่อจากฟังก์ชันไปยังทั้งเครือข่าย VPC และอินเทอร์เน็ตอาจถูกสิ้นสุดและแทนที่ในบางครั้งเมื่อมีการรีสตาร์ทหรืออัปเดตโครงสร้างพื้นฐานที่เกี่ยวข้อง หากแอปพลิเคชันของคุณใช้การเชื่อมต่อที่มีอายุการใช้งานยาวนานซ้ำ เราขอแนะนำให้คุณกำหนดค่าแอปพลิเคชันเพื่อสร้างการเชื่อมต่อใหม่เพื่อหลีกเลี่ยงการใช้การเชื่อมต่อที่ใช้งานไม่ได้ซ้ำ

การทดสอบการโหลดฟังก์ชัน

หากต้องการวัดจำนวนการเชื่อมต่อที่ฟังก์ชันดำเนินการโดยเฉลี่ย ให้ ทําการติดตั้งใช้งานเป็นฟังก์ชัน HTTP และใช้เฟรมเวิร์กการทดสอบประสิทธิภาพเพื่อเรียกใช้ที่ QPS ที่แน่นอน ตัวเลือกหนึ่งที่เป็นไปได้คือ Artillery ซึ่ง คุณเรียกใช้ได้ด้วยบรรทัดเดียวดังนี้

$ artillery quick -d 300 -r 30 URL

คำสั่งนี้จะดึงข้อมูล URL ที่ระบุที่ 30 QPS เป็นเวลา 300 วินาที

หลังจากทำการทดสอบแล้ว ให้ตรวจสอบการใช้งานโควต้าการเชื่อมต่อใน หน้าโควต้า API ของ Cloud Functions Cloud Console หากการใช้งานอยู่ที่ประมาณ 30 (หรือหลายๆ ครั้ง) อย่างสม่ำเสมอ แสดงว่าคุณ สร้างการเชื่อมต่อ 1 รายการ (หรือหลายรายการ) ในทุกการเรียกใช้ หลังจาก เพิ่มประสิทธิภาพโค้ดแล้ว คุณควรเห็นการเชื่อมต่อเพียงไม่กี่ครั้ง (10-30 ครั้ง) เฉพาะที่ จุดเริ่มต้นของการทดสอบ

นอกจากนี้ คุณยังเปรียบเทียบต้นทุน CPU ก่อนและหลังการเพิ่มประสิทธิภาพในแผนภาพโควต้า CPU ในหน้าเดียวกันได้ด้วย