Azure İşlevleri'da Python uygulamalarının aktarım hızı performansını geliştirme
Python kullanarak Azure İşlevleri için geliştirme yaparken işlevlerinizin performansını ve bu performansın işlev uygulamanızın ölçeklendiriliş şeklini nasıl etkilediğini anlamanız gerekir. Yüksek performanslı uygulamalar tasarlarken ihtiyaç daha önemlidir. İşlev uygulamalarınızı tasarlarken, yazarken ve yapılandırırken dikkate alınması gereken temel faktörler yatay ölçeklendirme ve aktarım hızı performans yapılandırmalarıdır.
Yatay ölçeklendirme
varsayılan olarak, Azure İşlevleri uygulamanızdaki yükü otomatik olarak izler ve gerektiğinde Python için daha fazla konak örneği oluşturur. Azure İşlevleri, queueTrigger için iletilerin yaşı ve kuyruk boyutu gibi örneklerin ne zaman ekleneceğine karar vermek üzere farklı tetikleyici türleri için yerleşik eşikleri kullanır. Bu eşikler kullanıcı tarafından yapılandırılamaz. Daha fazla bilgi için bkz. Azure İşlevleri'de olay temelli ölçeklendirme.
Aktarım hızı performansını iyileştirme
Varsayılan yapılandırmalar Azure İşlevleri uygulamaların çoğu için uygundur. Ancak, iş yükü profilinize göre yapılandırmalar kullanarak uygulamalarınızın aktarım hızının performansını geliştirebilirsiniz. İlk adım, çalıştırdığınız iş yükünün türünü anlamaktır.
İş yükü türü | İşlev uygulaması özellikleri | Örnekler |
---|---|---|
G/Ç bağlı | • Uygulamanın birçok eşzamanlı çağrıyı işlemesi gerekir. • Uygulama, ağ çağrıları ve disk okuma/yazma işlemleri gibi çok sayıda G/Ç olayını işler. |
• Web API'leri |
CPU'ya bağlı | • Uygulama, görüntü yeniden boyutlandırma gibi uzun süre çalışan hesaplamalar yapar. • Uygulama veri dönüştürme yapar. |
• Veri işleme • Makine öğrenmesi çıkarımı |
Gerçek dünya işlev iş yükleri genellikle G/Ç ve CPU bağlı bir karışımı olduğundan, gerçekçi üretim yükleri altında uygulamanın profilini oluşturmanız gerekir.
Performansa özgü yapılandırmalar
İşlev uygulamanızın iş yükü profilini anladıktan sonra, işlevlerinizin aktarım hızı performansını geliştirmek için kullanabileceğiniz yapılandırmalar aşağıdadır.
- Async
- Birden çok dil çalışanı
- Dil çalışanı işlemi içindeki en fazla çalışan sayısı
- Olay döngüsü
- Dikey Ölçeklendirme
Zaman Uyumsuz
Python tek iş parçacıklı bir çalışma zamanı olduğundan, Python için bir konak örneği varsayılan olarak bir kerede yalnızca bir işlev çağrısını işleyebilir. Çok sayıda G/Ç olayını işleyen ve/veya G/Ç'ye bağlı olan uygulamalar için, işlevleri zaman uyumsuz olarak çalıştırarak performansı önemli ölçüde geliştirebilirsiniz.
Bir işlevi zaman uyumsuz olarak çalıştırmak için, işlevi doğrudan asyncio ile çalıştıran deyimini kullanınasync def
:
async def main():
await some_nonblocking_socket_io_op()
Aşağıda, aiohttp http istemcisi kullanan HTTP tetikleyicisine sahip bir işlev örneği verilmişti:
import aiohttp
import azure.functions as func
async def main(req: func.HttpRequest) -> func.HttpResponse:
async with aiohttp.ClientSession() as client:
async with client.get("PUT_YOUR_URL_HERE") as response:
return func.HttpResponse(await response.text())
return func.HttpResponse(body='NotFound', status_code=404)
Anahtar sözcüğü olmayan async
bir işlev ThreadPoolExecutor iş parçacığı havuzunda otomatik olarak çalıştırılır:
# Runs in a ThreadPoolExecutor threadpool. Number of threads is defined by PYTHON_THREADPOOL_THREAD_COUNT.
# The example is intended to show how default synchronous functions are handled.
def main():
some_blocking_socket_io()
İşlevleri zaman uyumsuz olarak çalıştırmanın tam avantajını elde etmek için kodunuzda kullanılan G/Ç işleminin/kitaplığının da zaman uyumsuz olarak uygulanması gerekir. Zaman uyumsuz olarak tanımlanan işlevlerde zaman uyumlu G/Ç işlemlerinin kullanılması genel performansa zarar verebilir. Kullandığınız kitaplıklarda zaman uyumsuz sürüm uygulanmıyorsa, uygulamanızda olay döngüsünü yöneterek kodunuzu zaman uyumsuz olarak çalıştırmanın avantajını yine de elde edebilirsiniz.
Zaman uyumsuz desenler uygulayan istemci kitaplıklarına birkaç örnek aşağıda verilmiştir:
- aiohttp - Asyncio için Http istemcisi/sunucusu
- Akışlar API - Ağ bağlantısıyla çalışmak için üst düzey zaman uyumsuz/beklemeye hazır temel öğeler
- Janus Kuyruğu - Python için iş parçacığı güvenli zaman uyumsuz kuyruk
- pyzmq - ZeroMQ için Python bağlamaları
Python çalışanında zaman uyumsuzları anlama
İşlev imzasının önünde tanımladığınızda async
, Python işlevi bir eş yordam olarak işaretler. Eş yordam çağırdığınızda, bir olay döngüsüne görev olarak zamanlanabilir. Zaman uyumsuz bir işlevi çağırdığınızda await
, olay döngüsüne bir devamlılık kaydeder ve bu da olay döngüsünün bekleme süresi boyunca bir sonraki görevi işlemesine olanak tanır.
Python Çalışanımızda çalışan, olay döngüsünü müşterinin async
işleviyle paylaşır ve aynı anda birden çok isteği işleyebilecektir. Müşterilerimizin aiohttp ve pyzmq gibi zaman uyumsuz uyumlu kitaplıklardan yararlanmalarını kesinlikle öneririz. Bu önerilerin uygulanması, zaman uyumlu olarak uygulandığında işlevinizin aktarım hızını bu kitaplıklarla karşılaştırıldığında artırır.
Dekont
İşleviniz herhangi bir await
uygulama olmadan olarak async
bildirilirse, olay döngüsü engellendiğinden, Python çalışanının eşzamanlı istekleri işlemesini engelleyen işlevinizin performansı ciddi şekilde etkilenir.
Birden çok dil çalışanı işlemi kullanma
Varsayılan olarak her İşlev konak örneğinin tek bir dil çalışanı işlemi vardır. Uygulama ayarını kullanarak konak başına çalışan işlemlerinin sayısını artırabilirsiniz (10'a FUNCTIONS_WORKER_PROCESS_COUNT
kadar). Azure İşlevleri daha sonra eş zamanlı işlev çağrılarını bu çalışanlara eşit olarak dağıtmaya çalışır.
CPU bağlı uygulamalarda, dil çalışanlarının sayısını işlev uygulaması başına kullanılabilir çekirdek sayısıyla aynı veya daha yüksek olacak şekilde ayarlamanız gerekir. Daha fazla bilgi edinmek için bkz . Kullanılabilir örnek SKU'ları.
G/Ç'ye bağlı uygulamalar, çalışan işlemlerinin sayısını kullanılabilir çekirdek sayısının ötesinde artırmanın da avantajını elde edebilir. Gerekli bağlam anahtarlarının sayısının artması nedeniyle çalışan sayısını çok yüksek ayarlamanın genel performansı etkileyebileceğini unutmayın.
, FUNCTIONS_WORKER_PROCESS_COUNT
Azure İşlevleri talebi karşılamak için uygulamanızın ölçeğini genişletirken oluşturduğu her konak için geçerlidir.
Bir dil çalışanı işlemi içinde en fazla çalışan ayarlama
Zaman uyumsuz bölümünde belirtildiği gibi Python dil çalışanı işlevleri ve eş yordamları farklı şekilde ele alır . Coroutine, dil çalışanının üzerinde çalıştığı olay döngüsü içinde çalıştırılır. Öte yandan, bir işlev çağrısı, dil çalışanı tarafından iş parçacığı olarak tutulan threadPoolExecutor içinde çalıştırılır.
PYTHON_THREADPOOL_THREAD_COUNT uygulama ayarını kullanarak eşitleme işlevlerini çalıştırmak için izin verilen en fazla çalışanın değerini ayarlayabilirsiniz. Bu değer, Python'ın çağrıları zaman uyumsuz olarak yürütmek için çoğu max_worker
iş parçacığı havuzunu kullanmasına olanak tanıyan ThreadPoolExecutor nesnesinin bağımsız değişkenini ayarlarmax_worker
. , PYTHON_THREADPOOL_THREAD_COUNT
İşlevler ana bilgisayarının oluşturduğu her çalışan için geçerlidir ve Python yeni bir iş parçacığının ne zaman oluşturulacağını veya mevcut boşta olan iş parçacığının ne zaman yeniden kullanılması gerektiğine karar verir. Eski Python sürümleri (, 3.8
, 3.7
ve 3.6
) max_worker
için değer 1 olarak ayarlanır. Python sürümü 3.9
için olarak max_worker
ayarlanır None
.
CPU'ya bağlı uygulamalar için ayarı 1'den başlayarak ve iş yükünüzle denemeler yapınken artarak düşük bir sayıya tutmanız gerekir. Bu öneri, bağlam anahtarlarında harcanan süreyi azaltmak ve CPU'ya bağlı görevlerin bitmesini sağlamaktır.
G/Ç'ye bağlı uygulamalarda, her çağrı üzerinde çalışan iş parçacığı sayısını artırarak önemli kazançlar görmeniz gerekir. Python varsayılan değeri (çekirdek sayısı) + 4 ile başlayıp gördüğünüz aktarım hızı değerlerine göre ayarlamalar yapmak tavsiye edilir.
Karma iş yükleri uygulamalarında, aktarım hızını en üst düzeye çıkarmak için hem hem PYTHON_THREADPOOL_THREAD_COUNT
de FUNCTIONS_WORKER_PROCESS_COUNT
yapılandırmaları dengelemeniz gerekir. İşlev uygulamalarınızın en çok ne üzerinde zaman geçirdiğini anlamak için profil oluşturmanızı ve değerleri davranışlarına göre ayarlamanızı öneririz. Bu uygulama ayarları hakkında bilgi edinmek için bkz . Birden çok çalışan işlemi kullanma.
Dekont
Bu öneriler hem HTTP hem de HTTP ile tetiklenmeyen işlevler için geçerli olsa da, işlev uygulamalarınızdan beklenen performansı elde etmek için HTTP ile tetiklenmeyen işlevler için tetikleyiciye özgü diğer yapılandırmaları ayarlamanız gerekebilir. Bu konuda daha fazla bilgi için lütfen bu Güvenilir Azure İşlevleri için en iyi yöntemler konusuna bakın.
Olay döngüsünü yönetme
Zaman uyumsuz uyumlu üçüncü taraf kitaplıkları kullanmanız gerekir. Üçüncü taraf kitaplıklardan hiçbiri gereksinimlerinizi karşılamıyorsa, Azure İşlevleri olay döngülerini de yönetebilirsiniz. Olay döngülerini yönetmek, işlem kaynağı yönetiminde size daha fazla esneklik sağlar ve zaman uyumlu G/Ç kitaplıklarını eş yordamlara sarmalamanızı da mümkün kılar.
Yerleşik asyncio kitaplığını kullanarak Coroutines ve Görevler ile Olay Döngüsü'nü tartışan birçok yararlı Python resmi belgesi vardır.
Örnek olarak aşağıdaki istek kitaplığını ele alalım, bu kod parçacığı yöntemi eş zamanlı olarak SAMPLE_URL için birden çok web isteği çalıştırarak bir coroutine sarmak requests.get()
için asyncio kitaplığını kullanır.
import asyncio
import json
import logging
import azure.functions as func
from time import time
from requests import get, Response
async def invoke_get_request(eventloop: asyncio.AbstractEventLoop) -> Response:
# Wrap requests.get function into a coroutine
single_result = await eventloop.run_in_executor(
None, # using the default executor
get, # each task call invoke_get_request
'SAMPLE_URL' # the url to be passed into the requests.get function
)
return single_result
async def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
eventloop = asyncio.get_event_loop()
# Create 10 tasks for requests.get synchronous call
tasks = [
asyncio.create_task(
invoke_get_request(eventloop)
) for _ in range(10)
]
done_tasks, _ = await asyncio.wait(tasks)
status_codes = [d.result().status_code for d in done_tasks]
return func.HttpResponse(body=json.dumps(status_codes),
mimetype='application/json')
Dikey ölçeklendirme
Daha yüksek belirtimlere sahip premium plana yükselterek özellikle CPU'ya bağlı işlemlerde daha fazla işlem birimi elde edebilirsiniz. Daha yüksek işleme birimleriyle çalışan işlemlerinin sayısını kullanılabilir çekirdek sayısına göre ayarlayabilir ve daha yüksek paralellik derecesine ulaşabilirsiniz.
Sonraki adımlar
Python geliştirme Azure İşlevleri hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın: