مشاركة عبر


دراسة استخدام ذاكرة تطبيقات Python في Azure Functions

في أثناء أو بعد تطوير مشروع تطبيق دالة Python المحلي إلى Azure، من الجيد تحليل اختناقات الذاكرة المحتملة في وظائفك. يمكن أن تقلل هذه الاختناقات من أداء وظائفك وتؤدي إلى أخطاء. توضح لك الإرشادات التالية كيفية استخدام حزمة Python لملف تعريف الذاكرة، والتي توفر تحليل استهلاك الذاكرة سطرا سطرا لوظائفك أثناء تنفيذها.

إشعار

جمع معلومات الذاكرة مخصص فقط لتحليل بصمة الذاكرة في بيئات التطوير. الرجاء عدم تطبيق محلل الذاكرة على تطبيقات وظيفة الإنتاج.

المتطلبات الأساسية

قبل البدء في تطوير تطبيق دالة Python، يجب أن تستوفي هذه المتطلبات:

إذا لم يكن لديك اشتراك في Azure، فأنشئ حساب Azure مجاني قبل أن تبدأ.

عملية تحليل الذاكرة

  1. في requirements.txt، أضف memory-profiler للتأكد من أن الحزمة مجمعة مع التوزيع الخاص بك. إذا كنت تقوم بالتطوير على جهازك المحلي، فقد تحتاج إلى تنشيط بيئة Python الظاهرية والقيام بحل الحزمة بواسطة pip install -r requirements.txt.

  2. في البرنامج النصي للدالة (على سبيل المثال، __init__.py لنموذج برمجة Python v1 function_app.py لنموذج v2)، أضف الأسطر التالية أعلى الدالةmain(). تضمن هذه الأسطر أن يقوم المسجل الجذر بالإبلاغ عن أسماء المسجل الفرعي، بحيث يمكن تمييز سجلات جمع معلومات الذاكرة بواسطة البادئة memory_profiler_logs.

    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. قم بتطبيق المُحسِّن التالي فوق أي وظائف تحتاج إلى تحديد سمات الذاكرة. لا يعمل مصمم الديكور مباشرة على أسلوب نقطة main() إدخال المشغل. تحتاج إلى إنشاء وظائف فرعية وتزيينها. أيضا، بسبب مشكلة معروفة في محلل ملفات تعريف الذاكرة، عند تطبيقها على coroutine غير متزامن، تكون قيمة إرجاع coroutine دائما None.

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. اختبر محلل ملفات تعريف الذاكرة على جهازك المحلي باستخدام الأمر func host startAzure Functions Core Tools . عند استدعاء الدالات، يجب أن تنشئ تقرير استخدام الذاكرة. يحتوي التقرير على اسم الملف، سطر التعليمات البرمجية، استخدام الذاكرة، زيادة الذاكرة، ومحتوى السطر فيه.

  5. للتحقق من سجلات جمع معلومات الذاكرة على مثيل تطبيق دالة موجود في Azure، يمكنك الاستعلام عن سجلات جمع معلومات الذاكرة للاستدعاءات الأخيرة باستخدام استعلامات Kusto في Application Insights والسجلات.

    لقطة شاشة تعرض استخدام ذاكرة الاستعلام لتطبيق Python في Application Insights.

    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
    

مثال

فيما يلي مثال على إجراء جمع معلومات الذاكرة على مشغل HTTP غير متزامن ومتزامن، يسمى "HttpTriggerAsync" و"HttpTriggerSync" على التوالي. سنقوم بإنشاء تطبيق وظائف Python الذي يرسل ببساطة طلبات GET إلى الصفحة الرئيسية ل Microsoft.

إنشاء تطبيق دالة Python

يجب أن يتبع تطبيق دالة Python بنية المجلد المحددة من قِبل Azure Functions إلى سقالات توليد المشاريع، نوصي باستخدام الأدوات الأساسية لـ Azure Functions⁧ عن طريق تشغيل الأوامر التالية:

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

تحديث محتويات الملف

يحدد requirements.txt الحزم المستخدمة في مشروعنا. بالإضافة إلى حزمة أدوات تطوير البرمجيات ومحلل ذاكرة Azure Functions، نقدم aiohttp طلبات HTTP غير المتزامنة وrequestsمكالمات HTTP المتزامنة.

# requirements.txt

azure-functions
memory-profiler
aiohttp
requests

إنشاء مشغل HTTP غير المتزامن.

استبدل التعليمات البرمجية في مشغل HTTP غير المتزامن HttpTriggerAsync/__init__.py بالتعليمات البرمجية التالية، والتي تقوم بتكوين محلل ملفات تعريف الذاكرة وتنسيق مسجل الجذر وربط تدفق المسجل.

# 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

إنشاء مشغل HTTP المتزامن.

استبدل التعليمات البرمجية في مشغل HTTP غير المتزامن HttpTriggerSync/__init__.py بالتعليمات البرمجية التالية.

# 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

دراسة تطبيق دالة Python في بيئة التطوير المحلية

بعد إجراء التغييرات المذكورة أعلاه، هناك بضع خطوات أخرى لتهيئة بيئة Python الظاهرية لوقت تشغيل Azure Functions.

  1. فتح Windows PowerShell أو أي Linux shell تفضل.

  2. إنشاء بيئة افتراضية للـ Python عبر py -m venv .venvفي Windows، أو python3 -m venv .venv في لينكس.

  3. تنشيط بيئة Python الظاهرية باستخدام .venv\Scripts\Activate.ps1 في Windows PowerShell أو source .venv/bin/activate في Linux shell.

  4. استعادة تبعيات Python باستخدامpip install -r requirements.txt

  5. بدء وقت تشغيل Azure Functions محليًا باستخدام الأدوات الأساسية لـ Azure Functions⁧func host start

  6. أرسل طلب GET إلى https://localhost:7071/api/HttpTriggerAsync أو https://localhost:7071/api/HttpTriggerSync.

  7. يجب أن يظهر تقرير جمع معلومات الذاكرة مشابها للقسم التالي في Azure Functions Core Tools.

    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()
    

الخطوات التالية

للحصول على مزيدٍ من المعلومات حول تطوير Python في وظائف Azure، راجع الموارد التالية: