Ağ iletişimini optimize etme

Cloud Functions'ün basitliği, hızlı bir şekilde kod geliştirmenize ve 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 öncelikli bir konu gibi görünmeyebilir. Ancak dağıtımınız ölçeklendikçe kodunuzu optimize etmek giderek daha önemli hale gelir.

Bu belgede, işlevleriniz için ağ bağlantısını nasıl optimize edeceğiniz açıklanmaktadır. Ağ bağlantısını optimize etmenin avantajlarından bazıları şunlardır:

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

Kalıcı Bağlantıları Koruma

Bu bölümde, bir işlevde kalıcı bağlantıların nasıl sürdürüleceğine dair örnekler verilmiştir. Bu yapılmazsa bağlantı kotalarının hızla tükenmesi söz konusu olabilir.

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

  • HTTP/S
  • Google API'leri

HTTP/S İstekleri

Aşağıdaki optimize edilmiş kod snippet'inde, her işlev çağrısında yeni bir bağlantı oluşturmak yerine kalıcı bağlantıların nasıl sürdürüleceği gösterilmektedir:

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 göndermek için bir bağlantı havuzu kullanır. Bir istek nesnesi (flask.Request) alır ve yanıt metnini veya make_response kullanılarak 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 diğer istemci kitaplıkları (ör. Cloud Natural Language veya Cloud Spanner) için de geçerlidir. Performans iyileştirmelerinin, belirli istemci kitaplıklarının mevcut uygulamasına bağlı olabileceğini unutmayın.

Bir Pub/Sub istemci nesnesi oluşturmak, çağrı başına bir bağlantı ve iki DNS sorgusu oluşturur. 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ği kullanır. Bir istek nesnesi (flask.Request) alır ve yanıt metnini veya make_response kullanılarak 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, işlev dağıtımında bunu belirtmeyi unutmayın. Ortam değişkenlerini yapılandırma başlıklı makaleyi inceleyin.

Giden bağlantılar

Giden istek zaman aşımları

İşlevinizden VPC ağına gönderilen istekler, 10 dakikalık boşta kalma süresinden sonra zaman aşımına uğrar. İşlevinizden internete gönderilen istekler için 20 dakikalık boş zaman geçtikten sonra zaman aşımı olur.

Giden bağlantı sıfırlamaları

İşlevinizden hem VPC ağına hem de internete giden bağlantı akışları, temel altyapı yeniden başlatıldığında veya güncellendiğinde zaman zaman sonlandırılıp değiştirilebilir. Uygulamanız uzun süreli bağlantıları yeniden kullanıyorsa bağlantının tekrar kullanılmasını önlemek için uygulamanızı bağlantıları yeniden kuracak şekilde yapılandırmanız önerilir.

İşlevinizin yük testini yapma

İşlevinizin ortalama olarak kaç bağlantı kurduğunu ölçmek için işlevi HTTP işlevi olarak dağıtmanız ve belirli bir YGÇ'de çağırmak için 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, belirtilen URL'yi 300 saniye boyunca 30 QPS hızında getirir.

Testi yaptıktan sonra, Cloud Console'daki Cloud Functions API kotası sayfasında bağlantı kotanızın kullanımını kontrol edin. Kullanım sürekli olarak 30 civarındaysa (veya bunun katıysa) her çağrıda bir (veya birkaç) bağlantı kuruyorsunuz demektir. Kodunuzu optimize ettikten sonra, yalnızca testin başında birkaç (10-30) bağlantı gerçekleştiğini görürsünüz.

Aynı sayfadaki CPU kotası grafiğinde, optimizasyondan önce ve sonra CPU maliyetini de karşılaştırabilirsiniz.