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ının 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.