Joey
Joey

Reputation: 687

Azure Functions fails in load testing in combination with Azure Cosmos DB or SQL database

I got a large dataset of all the addresses in my country (3.8GB). I am creating an API which will query the database for one specific address and respond with basic JSON data (300bytes). The API is running in Python on Azure Functions.

So far everything works great. When I do a single request I get a response time of +/- 100-150ms. Great! but... If I try to load test the API with, let's say, 200 requests in 1 minute. The average response time is around 4-6 seconds.

This is what I tried so far

Is there some limit on the number of connections per database? The SQL Database or Cosmos DB doesn't seem to be the issue (% of CPU/Mem are good). I created a simple /status endpoint without the DB connection on the API which can handle 200 requests in 1 minute easily. Hopefully someone can push me in the right direction.

    import azure.functions as func
    import os
    
    from azure.functions import AsgiMiddleware
    from fastapi import Query
    from typing import Optional
    from api_app import app
    
    import azure.cosmos.documents as documents
    import azure.cosmos.cosmos_client as cosmos_client
    import azure.cosmos.exceptions as exceptions
    from azure.cosmos.partition_key import PartitionKey
    
    @app.get("/status")
    def get_status():
        return ({"status":  200})
    
    @app.get("/postcode_cosmosdb/{postcode}/{huisnummer}")
    async def postcode_cosmosdb(postcode: str, huisnummer: int):
        settings = {
            'host': os.environ.get('ACCOUNT_HOST', 'XXXXXX'),
            'master_key': os.environ.get('ACCOUNT_KEY', 'XXXXXX'),
            'database_id': os.environ.get('COSMOS_DATABASE', 'WoningAdressen'),
            'container_id': os.environ.get('COSMOS_CONTAINER', 'AdressenLight'),
        }
    
        HOST = settings['host']
        MASTER_KEY = settings['master_key']
        DATABASE_ID = settings['database_id']
        CONTAINER_ID = settings['container_id']
    
        client = cosmos_client.CosmosClient(HOST, {'masterKey': MASTER_KEY}, user_agent="CosmosDBPythonQuickstart", user_agent_overwrite=True)
        db = client.get_database_client(DATABASE_ID)
        container = db.get_container_client(CONTAINER_ID)
    
        items = list(container.query_items(
            query="SELECT l.postcode, l.huisnummer, l.huisletter, l.nummeraanduiding_id as bagid, l.gemeente FROM AdressenLight as l WHERE l.postcode=@postcode AND l.huisnummer=@huisnummer",
            parameters=[
                { "name":"@postcode", "value": postcode },
                { "name":"@huisnummer", "value": huisnummer }
            ]
        ))
    
        return items
    
    def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
        return AsgiMiddleware(app).handle(req, context)

Upvotes: 1

Views: 284

Answers (1)

tlt
tlt

Reputation: 15271

It is official recommendation to reuse clients across function invocations. That keeps number of connections small and calls more efficient.

Please refer to docs: https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections

Upvotes: 1

Related Questions