Cloud Functions'nın basitliği, kodu hızlı bir şekilde geliştirmenize ve sunucusuz bir ortamda çalıştırmanıza olanak tanır. Orta ölçekte işlev çalıştırmanın maliyeti düşüktür ve kodunuzu optimize etmek yüksek öncelikli bir görev 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ğ iletişimi optimizasyonunun nasıl yapılacağı açıklanmaktadır. Ağ optimizasyonunun bazı avantajları şunlardır:
- Her işlev çağrısında yeni giden bağlantılar oluşturmak için harcanan CPU süresini azaltın.
- Bağlantı veya DNS kotalarının tükenme olasılığını azaltır.
Kalıcı Bağlantıları Sürdürme
Bu bölümde, bir fonksiyonda kalıcı bağlantıların nasıl korunacağına dair örnekler verilmektedir. Bu yapılmadığı takdirde bağlantı kotaları hızlıca tükenebilir.
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 snippet'inde, her işlev çağrısında yeni bir bağlantı oluşturmak yerine kalıcı bağlantıların nasıl korunacağı 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 bağlantı havuzu kullanır. Bir istek nesnesi (flask.Request
) alır ve yanıt metnini ya da make_response
kullanılarak Response
nesnesine dönüştürülebilen 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ı için de geçerlidir. Örneğin, Cloud Natural Language veya Cloud Spanner. Performans iyileştirmelerinin, belirli istemci kitaplıklarının mevcut uygulamasına bağlı olabileceğini unutmayın.
Pub/Sub istemci nesnesi oluşturmak, her çağırmada bir bağlantı ve iki DNS sorgusuyla sonuçlanır. Gereksiz bağlantıları ve DNS sorgularını önlemek için aşağıdaki örnekte gösterildiği gibi genel kapsamda Pub/Sub istemci nesnesi 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. İstek nesnesi (flask.Request
) alır ve yanıt metnini ya da make_response
kullanılarak Response
nesnesine dönüştürülebilen 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. 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 yapılan istekler için 10 dakika boşta kalma süresinden sonra zaman aşımı gerçekleşir. İşlevinizin internete yaptığı isteklerde 20 dakikalık boşta kalma süresinden sonra zaman aşımı oluşur.
Giden bağlantı sıfırlamaları
Temel altyapı yeniden başlatıldığında veya güncellendiğinde işlevinizden hem VPC ağına hem de internete giden bağlantı akışları zaman zaman sonlandırılıp değiştirilebilir. Uygulamanız uzun süreli bağlantıları yeniden kullanıyorsa ölü bağlantıların yeniden kullanılmasını önlemek için uygulamanızı bağlantıları yeniden oluşturacak şekilde yapılandırmanızı öneririz.
İşlevinizi Yük Testine Tabi Tutma
İşlevinizin ortalama olarak kaç bağlantı gerçekleştirdiğini ölçmek için işlevinizi bir HTTP işlevi olarak dağıtın ve belirli bir sorgu/saniye hızında çağırmak için bir performans testi çerçevesi kullanın. Olası bir seçenek olan Artillery'yi tek bir satırla çağırabilirsiniz:
$ artillery quick -d 300 -r 30 URL
Bu komut, belirtilen URL'yi 300 saniye boyunca 30 QPS hızında getirir.
Testi gerçekleştirdikten 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ında (veya 30'un katları) ise her çağrıda bir (veya birkaç) bağlantı oluşturuyorsunuz demektir. Kodunuzu optimize ettikten sonra, testin yalnızca başında birkaç (10-30) bağlantı oluştuğunu görmeniz gerekir.
Aynı sayfadaki CPU kotası grafiğinde optimizasyondan önceki ve sonraki CPU maliyetini de karşılaştırabilirsiniz.