Azure İşlevleri'de Python uygulamalarının bellek kullanımının profilini oluşturma

Geliştirme sırasında veya yerel Python işlev uygulaması projenizi Azure'a dağıttığınızda işlevlerinizdeki olası bellek sorunlarını analiz etmek iyi bir uygulamadır. Bu tür performans sorunları işlevlerinizin performansını düşürebilir ve hatalara yol açabilir. Aşağıdaki yönergelerde, yürütülürken işlevlerinizin satır satır bellek tüketimi analizini sağlayan bellek profili oluşturucu Python paketinin nasıl kullanılacağı gösterilmektedir.

Not

Bellek profili oluşturma yalnızca geliştirme ortamlarında bellek ayak izi analizi için tasarlanmıştır. Lütfen bellek profil oluşturucuyu üretim işlevi uygulamalarına uygulamayın.

Önkoşullar

Python işlev uygulaması geliştirmeye başlamadan önce şu gereksinimleri karşılamanız gerekir:

Azure hesabınız yoksa, başlamadan önce ücretsiz hesap oluşturun.

Bellek profili oluşturma işlemi

  1. Paketin dağıtımınızla birlikte paketlenmesini sağlamak için requirements.txt dosyanıza memory-profiler ekleyin. Yerel makinenizde geliştirme yapıyorsanız, bir Python sanal ortamını etkinleştirmek ve pip install -r requirements.txt ile paket çözümlemesi yapmak isteyebilirsiniz.

  2. İşlev betiğinizde (örneğin, Python v1 programlama modeli için __init__.py ve v2 modeli için function_app.py ), işlevin main() üzerine aşağıdaki satırları ekleyin. Bu satırlar, kök günlükleyicinin alt günlükleyici adlarını raporlamasını sağlar; böylece bellek profilleme günlükleri memory_profiler_logs ön ekiyle ayırt edilebilir.

    import logging
    import memory_profiler
    root_logger = logging.getLogger()
    root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
    profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
    
  3. Bellek profili oluşturma gerektiren tüm işlevlerin üzerine aşağıdaki dekoratörü uygulayın. Dekoratör doğrudan tetikleyici giriş noktası main() yönteminde çalışmaz. Alt işlevleri oluşturmanız ve süslemeniz gerekir. Ayrıca, bellek profil oluşturucudaki bilinen bir sorun nedeniyle, asenkron bir coroutine’e uygulandığında coroutine’in dönüş değeri her zaman None olur.

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. Azure İşlevleri Core Tools komutunu func host startkullanarak yerel makinenizde bellek profil oluşturucusunu test edin. İşlevleri çağırdığınızda, bir bellek kullanım raporu oluşturmaları gerekir. Rapor dosya adını, kod satırını, bellek kullanımını, bellek artışını ve içindeki satır içeriğini içerir.

  5. Azure’daki mevcut bir işlev uygulaması örneğindeki bellek profilleme günlüklerini denetlemek için, Application Insights’taki Günlükler’de Kusto sorgularını kullanarak son çağrılara ilişkin bellek profilleme günlüklerini sorgulayabilirsiniz.

    Application Insights'ta bir Python uygulamasının sorgu belleği kullanımını gösteren ekran görüntüsü.

    traces
    | where timestamp > ago(1d)
    | where message startswith_cs "memory_profiler_logs:"
    | parse message with "memory_profiler_logs: " LineNumber "  " TotalMem_MiB "  " IncreMem_MiB "  " Occurrences "  " Contents
    | union (
        traces
        | where timestamp > ago(1d)
        | where message startswith_cs "memory_profiler_logs: Filename: "
        | parse message with "memory_profiler_logs: Filename: " FileName
        | project timestamp, FileName, itemId
    )
    | project timestamp, LineNumber=iff(FileName != "", FileName, LineNumber), TotalMem_MiB, IncreMem_MiB, Occurrences, Contents, RequestId=itemId
    | order by timestamp asc
    

Örnek

Burada sırasıyla "HttpTriggerAsync" ve "HttpTriggerSync" adlı zaman uyumsuz ve zaman uyumlu bir HTTP tetikleyicisinde bellek profili oluşturma işlemi gerçekleştirme örneği verilmiştir. Microsoft'un giriş sayfasına GET istekleri gönderen bir Python işlev uygulaması oluşturacağız.

Python işlev uygulaması oluşturma

Python işlev uygulaması belirtilen Azure İşlevleri klasör yapısını izlemelidir. Projenin iskelesini yapmak için aşağıdaki komutları çalıştırarak Azure İşlevleri Core Tools'u kullanmanızı öneririz:

func init PythonMemoryProfilingDemo --python
cd PythonMemoryProfilingDemo
func new -l python -t HttpTrigger -n HttpTriggerAsync -a anonymous
func new -l python -t HttpTrigger -n HttpTriggerSync -a anonymous

Dosya içeriğini güncelleştirme

requirements.txt, projemizde kullanılan paketleri tanımlar. Azure İşlevleri SDK’sı ve bellek profil oluşturucunun yanı sıra, zaman uyumsuz HTTP istekleri için aiohttp ve zaman uyumlu HTTP çağrıları için requests sunuyoruz.

# requirements.txt

azure-functions
memory-profiler
aiohttp
requests

Zaman uyumsuz HTTP tetikleyicisini oluşturun.

Asenkron HTTP tetikleyicisindeki HttpTriggerAsync/__init__.py kodunu, bellek profilleyicisini, kök günlükleyici biçimini ve günlükleyici akış bağlamasını yapılandıran aşağıdaki kodla değiştirin.

# HttpTriggerAsync/__init__.py

import azure.functions as func
import aiohttp
import logging
import memory_profiler

# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)

async def main(req: func.HttpRequest) -> func.HttpResponse:
    await get_microsoft_page_async('https://microsoft.com')
    return func.HttpResponse(
        f"Microsoft page loaded.",
        status_code=200
    )

@memory_profiler.profile(stream=profiler_logstream)
async def get_microsoft_page_async(url: str):
    async with aiohttp.ClientSession() as client:
        async with client.get(url) as response:
            await response.text()
    # @memory_profiler.profile does not support return for coroutines.
    # All returns become None in the parent functions.
    # GitHub Issue: https://github.com/pythonprofilers/memory_profiler/issues/289

Zaman uyumlu HTTP tetikleyicisini oluşturun.

HttpTriggerSync/__init__.py zaman uyumsuz HTTP tetikleyicisindeki kodu aşağıdaki kodla değiştirin.

# HttpTriggerSync/__init__.py

import azure.functions as func
import requests
import logging
import memory_profiler

# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)

def main(req: func.HttpRequest) -> func.HttpResponse:
    content = profile_get_request('https://microsoft.com')
    return func.HttpResponse(
        f"Microsoft page response size: {len(content)}",
        status_code=200
    )

@memory_profiler.profile(stream=profiler_logstream)
def profile_get_request(url: str):
    response = requests.get(url)
    return response.content

Yerel geliştirme ortamında Python işlev uygulamasının profilini oluşturma

Yukarıdaki değişiklikleri yaptıktan sonra, Azure İşlevleri çalışma zamanı için python sanal ortamını başlatmaya yönelik birkaç adım daha vardır.

  1. Windows PowerShell’i veya tercih ettiğiniz herhangi bir Linux kabuğunu açın.

  2. Windows'da veya py -m venv .venv Linux'ta kullanarak python3 -m venv .venv bir Python sanal ortamı oluşturun.

  3. Python sanal ortamını Windows PowerShell'de .venv\Scripts\Activate.ps1 veya Linux kabuğunda source .venv/bin/activate ile etkinleştirin.

  4. ile Python bağımlılıklarını geri yükleme pip install -r requirements.txt

  5. Azure İşlevleri Core Araçları ile Azure İşlevleri çalışma zamanını yerel olarak başlatmafunc host start

  6. https://localhost:7071/api/HttpTriggerAsync veya https://localhost:7071/api/HttpTriggerSync öğesine bir GET isteği gönderin.

  7. Azure İşlevleri Temel Araçları'nda aşağıdaki bölüme benzer bir bellek profili oluşturma raporu göstermelidir.

    Filename: <ProjectRoot>\HttpTriggerAsync\__init__.py
    Line #    Mem usage    Increment  Occurrences   Line Contents
    ============================================================
        19     45.1 MiB     45.1 MiB           1   @memory_profiler.profile
        20                                         async def get_microsoft_page_async(url: str):
        21     45.1 MiB      0.0 MiB           1       async with aiohttp.ClientSession() as client:
        22     46.6 MiB      1.5 MiB          10           async with client.get(url) as response:
        23     47.6 MiB      1.0 MiB           4               await response.text()
    

Sonraki adımlar

Python geliştirme Azure İşlevleri hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın: