Ağ oluşturmayı optimize etme

Cloud Functions'ın basitliği, hızla kod geliştirmenize ve onu sunucusuz bir ortamda çalıştırmanıza olanak tanır. Orta ölçekte, işlevleri çalıştırmanın maliyeti düşüktür ve kodunuzu optimize etmek yüksek bir öncelik gibi görünmeyebilir. Ancak dağıtımınız büyüdükçe kodunuzu optimize etmek giderek daha önemli hale gelir.

Bu belgede, işlevleriniz için ağ iletişimini nasıl optimize edebileceğiniz açıklanmaktadır. Ağı optimize etmenin faydalarından bazıları şunlardır:

  • Her işlev çağrısında yeni bağlantılar kurmak için harcanan CPU süresini azaltın.
  • Bağlantının veya DNS kotalarının tükenmesi olasılığını azaltın.

Kalıcı Bağlantıları Korumak

Bu bölümde bir işlevde kalıcı bağlantıların nasıl sürdürüleceğine ilişkin örnekler verilmektedir. Bunun yapılmaması, bağlantı kotalarının hızla tükenmesine neden olabilir.

Bu bölümde aşağıdaki senaryolar ele alınmaktadır:

  • HTTP/S
  • Google API'leri

HTTP/S İstekleri

Aşağıdaki optimize edilmiş kod parçacığı, her işlev çağrısında yeni bir bağlantı oluşturmak yerine kalıcı bağlantıların nasıl korunacağını gösterir:

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

Bu HTTP işlevi, HTTP istekleri yapmak için bir bağlantı havuzu kullanır. Bir istek nesnesini ( flask.Request ) alır ve yanıt metnini veya make_response kullanılarak bir Response nesnesine dönüştürülebilecek herhangi bir değer kümesini döndürür.

Google API'lerine erişme

Aşağıdaki örnekte Cloud Pub/Sub kullanılmaktadır ancak bu yaklaşım Cloud Natural Language veya Cloud Spanner gibi diğer istemci kitaplıkları için de işe yarar. Performans iyileştirmelerinin belirli istemci kitaplıklarının mevcut uygulamasına bağlı olabileceğini unutmayın.

Pub/Sub istemci nesnesi oluşturmak, çağrı başına bir bağlantı ve iki DNS sorgusu ile sonuçlanır. Gereksiz bağlantıları ve DNS sorgularını önlemek için Pub/Sub istemci nesnesini aşağıdaki örnekte gösterildiği gibi genel kapsamda oluşturun:

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

Bu HTTP işlevi, işlev çağrısı başına gereken bağlantı sayısını azaltmak için önbelleğe alınmış bir istemci kitaplığı örneğini kullanır. Bir istek nesnesini ( flask.Request ) alır ve yanıt metnini veya make_response kullanılarak bir Response nesnesine dönüştürülebilecek herhangi bir değer kümesini döndürür.

GCP_PROJECT ortam değişkeni Python 3.7 çalışma zamanında otomatik olarak ayarlanır. Daha sonraki çalışma zamanlarında, bunu işlev dağıtımında belirttiğinizden emin olun. Bkz . Ortam değişkenlerini yapılandırma .

İşlevinizi Yük Testi

İşlevinizin ortalama olarak kaç bağlantı gerçekleştirdiğini ölçmek için, onu bir HTTP işlevi olarak dağıtmanız ve onu belirli QPS'de çağırmak için bir performans testi çerçevesi kullanmanız yeterlidir. Olası seçeneklerden biri, tek bir satırla çağırabileceğiniz Artillery'dir :

$ artillery quick -d 300 -r 30 URL

Bu komut verilen URL'yi 300 saniye boyunca 30 QPS hızında getirir.

Testi gerçekleştirdikten sonra Cloud Console'daki Cloud Functions API kota sayfasında bağlantı kotanızın kullanımını kontrol edin. Kullanım sürekli olarak 30 (veya onun katları) civarındaysa, her çağrıda bir (veya daha fazla) bağlantı kuruyorsunuz demektir. Kodunuzu optimize ettikten sonra, yalnızca testin başlangıcında birkaç (10-30) bağlantının oluştuğunu görmelisiniz.

Aynı sayfadaki CPU kota grafiğinde optimizasyon öncesi ve sonrası CPU maliyetini de karşılaştırabilirsiniz.