Tối ưu hóa mạng

Tính đơn giản của Cloud Functions cho phép bạn nhanh chóng phát triển mã và chạy mã đó trong môi trường không có máy chủ. Ở quy mô vừa phải, chi phí chạy các hàm thấp và việc tối ưu hóa mã của bạn có vẻ không phải là ưu tiên cao. Tuy nhiên, khi quy mô triển khai của bạn tăng lên, việc tối ưu hóa mã của bạn ngày càng trở nên quan trọng.

Tài liệu này mô tả cách tối ưu hóa mạng cho các chức năng của bạn. Một số lợi ích của việc tối ưu hóa mạng như sau:

  • Giảm thời gian CPU dành cho việc thiết lập kết nối mới ở mỗi lệnh gọi hàm.
  • Giảm khả năng hết kết nối hoặc hạn ngạch DNS.

Duy trì kết nối liên tục

Phần này đưa ra các ví dụ về cách duy trì các kết nối liên tục trong một hàm. Nếu không làm như vậy có thể dẫn đến việc cạn kiệt nhanh chóng hạn ngạch kết nối.

Các tình huống sau đây được đề cập trong phần này:

  • HTTP/S
  • API Google

Yêu cầu HTTP/S

Đoạn mã được tối ưu hóa bên dưới cho thấy cách duy trì các kết nối liên tục thay vì tạo kết nối mới sau mỗi lần gọi hàm:

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!")
    

Hàm HTTP này sử dụng nhóm kết nối để thực hiện các yêu cầu HTTP. Nó nhận một đối tượng yêu cầu ( flask.Request ) và trả về văn bản phản hồi hoặc bất kỳ tập hợp giá trị nào có thể được chuyển thành đối tượng Response bằng cách sử dụng make_response .

Truy cập API của Google

Ví dụ bên dưới sử dụng Cloud Pub/Sub , nhưng cách tiếp cận này cũng hiệu quả với các thư viện máy khách khác—ví dụ: Cloud Natural Language hoặc Cloud Spanner . Lưu ý rằng việc cải thiện hiệu suất có thể phụ thuộc vào việc triển khai hiện tại của các thư viện máy khách cụ thể.

Việc tạo một đối tượng máy khách Pub/Sub sẽ tạo ra một kết nối và hai truy vấn DNS cho mỗi lệnh gọi. Để tránh các kết nối và truy vấn DNS không cần thiết, hãy tạo đối tượng máy khách Pub/Sub trong phạm vi toàn cầu như trong mẫu bên dưới:

nút.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")
    

Hàm HTTP này sử dụng một phiên bản thư viện máy khách được lưu trong bộ nhớ đệm để giảm số lượng kết nối cần thiết cho mỗi lần gọi hàm. Nó nhận một đối tượng yêu cầu ( flask.Request ) và trả về văn bản phản hồi hoặc bất kỳ tập hợp giá trị nào có thể được chuyển thành đối tượng Response bằng cách sử dụng make_response .

Biến môi trường GCP_PROJECT được đặt tự động trong thời gian chạy Python 3.7. Trong các thời gian chạy sau này, hãy đảm bảo chỉ định nó khi triển khai chức năng. Xem Định cấu hình biến môi trường .

Kiểm tra tải chức năng của bạn

Để đo lường trung bình có bao nhiêu kết nối mà chức năng của bạn thực hiện, chỉ cần triển khai nó dưới dạng hàm HTTP và sử dụng khung kiểm tra hiệu suất để gọi nó ở QPS nhất định. Một lựa chọn khả thi là Artillery , bạn có thể gọi bằng một dòng duy nhất:

$ artillery quick -d 300 -r 30 URL

Lệnh này tìm nạp URL đã cho ở tốc độ 30 QPS trong 300 giây.

Sau khi thực hiện kiểm tra, hãy kiểm tra mức sử dụng hạn ngạch kết nối của bạn trên trang hạn ngạch API Cloud Functions trong Cloud Console. Nếu mức sử dụng nhất quán ở khoảng 30 (hoặc bội số của nó), thì bạn đang thiết lập một (hoặc một số) kết nối trong mỗi lệnh gọi. Sau khi tối ưu hóa mã của mình, bạn sẽ thấy một vài (10-30) kết nối chỉ xuất hiện khi bắt đầu thử nghiệm.

Bạn cũng có thể so sánh chi phí CPU trước và sau khi tối ưu hóa trên biểu đồ hạn ngạch CPU trên cùng một trang.