İpuçları ve püf noktaları

Bu belgede Cloud Functions'ı tasarlama, uygulama, test etme ve dağıtmayla ilgili en iyi uygulamalar açıklanmaktadır.

Doğruluk

Bu bölümde Cloud Functions'ın tasarlanması ve uygulanmasıyla ilgili genel en iyi uygulamalar açıklanmaktadır.

Iempotent fonksiyonlar yazma

İşlevleriniz, birden fazla kez çağrılsa bile aynı sonucu üretmelidir. Bu sayede, önceki çağrı kodunuzun ortasında başarısız olursa çağrıyı yeniden deneyebilirsiniz. Daha fazla bilgi için etkinliğe dayalı işlevleri yeniden deneme bölümüne bakın.

Arka plan etkinlikleri başlatma

Arka plan etkinliği, işleviniz sonlandırıldıktan sonra gerçekleşen her şeydir. İşlev geri döndüğünde veya başka bir şekilde (ör. Node.js etkinlik odaklı işlevlerinde callback bağımsız değişkenini çağırarak) tamamlama sinyalini verdiğinde işlev çağrısı biter. Kontrollü sonlandırmadan sonra çalıştırılan kodlar CPU'ya erişemez ve herhangi bir ilerleme kaydetmez.

Ayrıca, aynı ortamda bir sonraki çağrı yürütüldüğünde arka plan etkinliğiniz devam ederek yeni çağrıyı engeller. Bu durum, beklenmedik davranışlara ve teşhis edilmesi zor hatalara yol açabilir. Bir işlev sona erdikten sonra ağa erişmek genellikle bağlantıların sıfırlanmasına yol açar (ECONNRESET hata kodu).

Arka plan etkinliği genellikle çağrının tamamlandığını belirten satırdan sonra günlüğe kaydedilen her şey bulılarak, bağımsız çağrılarla ilişkili günlüklerde algılanabilir. Arka plan etkinliği bazen kodun daha derinlerine gömülebilir. Özellikle de geri çağırma veya zamanlayıcı gibi eşzamansız işlemler söz konusu olduğunda bu işlemler yararlı olur. İşlevi sonlandırmadan önce tüm eşzamansız işlemlerin tamamlandığından emin olmak için kodunuzu inceleyin.

Geçici dosyaları her zaman sil

Geçici dizindeki yerel disk depolama alanı, bellek içi dosya sistemidir. Yazdığınız dosyalar, işleviniz için kullanılabilir olan belleği kullanır ve bazen çağrılar arasında devam eder. Bu dosyaların açıkça silinmemesi, sonunda bellek dışı hatasına ve sonrasında baştan başlatmaya neden olabilir.

Tek bir işlev tarafından kullanılan belleği, GCP Console'daki işlev listesinde ve Bellek kullanımı grafiğinde seçerek görebilirsiniz.

Geçici dizinin dışına yazmaya çalışmayın ve dosya yolları oluşturmak için platformdan/işletim sisteminden bağımsız yöntemler kullandığınızdan emin olun.

Ardışık düzen kullanarak daha büyük dosyaları işlerken bellek gereksinimlerini azaltabilirsiniz. Örneğin, okuma akışı oluşturarak, akış tabanlı bir işlemden geçirerek ve çıkış akışını doğrudan Cloud Storage'a yazarak Cloud Storage'da bir dosyayı işleyebilirsiniz.

Functions Framework

Bir işlev dağıttığınızda Functions Çerçevesi, mevcut sürümü kullanılarak otomatik bir şekilde bağımlılık olarak eklenir. Aynı bağımlılıkların farklı ortamlarda tutarlı bir şekilde yüklendiğinden emin olmak için işlevinizi Functions Çerçevesi'nin belirli bir sürümüne sabitlemenizi öneririz.

Bunu yapmak için tercih ettiğiniz sürümü ilgili kilit dosyasına ekleyin (örneğin, Node.js için package-lock.json veya Python için requirements.txt).

Araçlar

Bu bölümde Cloud Functions'ı uygulamak, test etmek ve etkileşimde bulunmak için araçların nasıl kullanılacağıyla ilgili yönergeler sunulmaktadır.

Yerel gelişim

İşlev dağıtımı biraz zaman alır. Bu nedenle, işlevinizin kodunu yerel olarak test etmek genellikle daha hızlıdır.

Firebase geliştiricileri, Firebase CLI Cloud Functions Emulator'ı kullanabilir.

E-posta göndermek için Sendgrid'i kullanma

Cloud Functions, bağlantı noktası 25'te giden bağlantılara izin vermez. Bu nedenle, bir SMTP sunucusuna güvenli olmayan bağlantılar oluşturamazsınız. E-posta göndermenin önerilen yolu SendGrid'i kullanmaktır. Google Compute Engine ile ilgili Örnekten E-posta Gönderme eğiticisinde e-posta göndermeyle ilgili diğer seçenekleri bulabilirsiniz.

Performans

Bu bölümde, performansı optimize etmeye yönelik en iyi uygulamalar açıklanmaktadır.

Bağımlılıkları akıllıca kullanın

İşlevler durum bilgisiz olduğundan, yürütme ortamı genellikle sıfırdan başlatılır (baştan başlatma olarak bilinen işlem sırasında). Soğuk başlatma gerçekleştiğinde, işlevin genel bağlamı değerlendirilir.

İşlevleriniz, modülleri içe aktarıyorsa bu modüllerin yükleme süresi, baştan başlatma sırasında çağrı gecikmesini artırabilir. Bağımlılıkları doğru şekilde yükleyerek ve işlevinizin kullanmadığı bağımlılıkları yüklemeyerek bu gecikmeyi ve işlevinizi dağıtmak için gereken süreyi azaltabilirsiniz.

Gelecekteki çağrılarda nesneleri yeniden kullanmak için global değişkenler kullanma

Cloud Functions işlevinin durumunun gelecekteki çağrılar için korunacağı garanti edilmez. Ancak Cloud Functions genellikle önceki bir çağrının yürütme ortamını geri dönüştürür. Global kapsamda bir değişken tanımlarsanız bu değişkenin değeri, yeniden hesaplamaya gerek kalmadan sonraki çağrılarda yeniden kullanılabilir.

Bu şekilde, her işlev çağrısında yeniden oluşturulması pahalı olabilecek nesneleri önbelleğe alabilirsiniz. Bu tür nesnelerin işlev gövdesinden global kapsama taşınması, önemli performans iyileştirmeleri sağlayabilir. Aşağıdaki örnek, işlev örneği başına yalnızca bir kez ağır nesne oluşturur ve bunu belirtilen örneğe ulaşan tüm işlev çağrılarında paylaşır:

Node.js

console.log('Global scope');
const perInstance = heavyComputation();
const functions = require('firebase-functions');

exports.function = functions.https.onRequest((req, res) => {
  console.log('Function invocation');
  const perFunction = lightweightComputation();

  res.send(`Per instance: ${perInstance}, per function: ${perFunction}`);
});

Python

import time

from firebase_functions import https_fn

# Placeholder
def heavy_computation():
  return time.time()

# Placeholder
def light_computation():
  return time.time()

# Global (instance-wide) scope
# This computation runs at instance cold-start
instance_var = heavy_computation()

@https_fn.on_request()
def scope_demo(request):

  # Per-function scope
  # This computation runs every time this function is called
  function_var = light_computation()
  return https_fn.Response(f"Instance: {instance_var}; function: {function_var}")
  

Bu HTTP işlevi, bir istek nesnesini (flask.Request) alır ve yanıt metnini veya make_response kullanarak Response nesnesine dönüştürülebilecek herhangi bir değer grubunu döndürür.

Ağ bağlantılarını, kitaplık referanslarını ve API istemci nesnelerini global kapsamda önbelleğe almak özellikle önemlidir. Örnekler için Ağ İletişimini Optimize Etme bölümüne bakın.

Genel değişkenlerin geç ilk kullanıma hazırlanması

Değişkenleri genel kapsamda başlatırsanız başlatma kodu her zaman baştan başlatma çağrısı aracılığıyla yürütülür ve işlevinizin gecikme süresi artar. Bazı durumlarda bu, try/catch blokunda uygun şekilde işlenmemeleri halinde çağrılan hizmetlerin zaman aşımına uğramasına neden olur. Bazı nesneler tüm kod yollarında kullanılmıyorsa bunları istediğiniz zaman geç başlatmayı deneyin:

Node.js

const functions = require('firebase-functions');
let myCostlyVariable;

exports.function = functions.https.onRequest((req, res) => {
  doUsualWork();
  if(unlikelyCondition()){
      myCostlyVariable = myCostlyVariable || buildCostlyVariable();
  }
  res.status(200).send('OK');
});

Python

from firebase_functions import https_fn

# Always initialized (at cold-start)
non_lazy_global = file_wide_computation()

# Declared at cold-start, but only initialized if/when the function executes
lazy_global = None

@https_fn.on_request()
def lazy_globals(request):

  global lazy_global, non_lazy_global

  # This value is initialized only if (and when) the function is called
  if not lazy_global:
      lazy_global = function_specific_computation()

  return https_fn.Response(f"Lazy: {lazy_global}, non-lazy: {non_lazy_global}.")
  

Bu HTTP işlevi, geç başlatılan genel değerleri kullanır. Bir istek nesnesini (flask.Request) alır ve yanıt metnini veya make_response kullanılarak Response nesnesine dönüştürülebilecek herhangi bir değer grubunu döndürür.

Bu, özellikle tek bir dosyada birden fazla işlev tanımlarsanız ve farklı işlevler farklı değişkenler kullanıyorsa önemlidir. Geç başlatma kullanmadığınız sürece, kaynakları başlatılan ancak hiç kullanılmayan değişkenler için boşa harcayabilirsiniz.

Minimum örnek sayısı ayarlayarak baştan başlatma sayısını azaltın

Varsayılan olarak Cloud Functions, örnek sayısını gelen isteklerin sayısına göre ölçeklendirir. Cloud Functions'ın istekleri sunmaya hazır durumda tutması gereken minimum örnek sayısını belirleyerek bu varsayılan davranışı değiştirebilirsiniz. Minimum örnek sayısı belirlemek, uygulamanızın baştan başlatılmasını azaltır. Uygulamanız gecikmeye duyarlıysa minimum bir örnek sayısı belirlemenizi öneririz.

Bu çalışma zamanı seçenekleri hakkında daha fazla bilgi için Ölçeklendirme davranışını kontrol etme bölümüne bakın.

Ek kaynaklar

"Google Cloud Performans Atlası"nın Cloud Functions Soğuk Başlatma Süresi videosundan performansı optimize etme hakkında daha fazla bilgi edinebilirsiniz.