V_B
V_B

Reputation: 1569

Azure Function input and output binding object are Shared or created in each request

I am using Azure function : Timer Trigger and Cosmos DB feed trigger.

Timer Trigger Function

I have Output binding of Cosmos DB in Timer Trigger function. I am creating connection with Service Bus client and reading messages in batch and uploading in Cosmos DB as shown below. My question is for every runtime Cosmos DB connection will be created? if yes, how i can share the connection? How can i improve SB connection as well so every runtime it will not create new connection. Am I doing it right way in terms of performance?

enter image description here

Cosmos DB feed trigger

In this function I have Cosmos DB as an trigger and outbound with SB. For every request new connection will be created or function will reuse existing object for both Cosmos and SB connection?

enter image description here

Upvotes: 0

Views: 831

Answers (2)

Sean Feldman
Sean Feldman

Reputation: 26057

Another alternative would be to have a Service Bus trigger and add a document as a message arrives instead of executing a timer and handling a batch. This approach includes the following benefits:

  1. No need to worry about the broker connection as it's handled by Functions.
  2. Less/simpler code. For example, you can receive the message deserialized into a POCO w/o going through manual deserialization.
  3. Alignment with an event-driven approach and not a time-based batch.

Upvotes: 1

Harshita Singh
Harshita Singh

Reputation: 4870

AFAIK, there are three recommended ways to share expensive data between functions on a server to improve performance:

  1. Use static client variables: Static variables are reused for every function invocation, instead of creating a new one, this saves memory and gives performance benefits. When the load is less, only one server instance is created for functions in background, so static variables are reused for multiple functions invocations within the same server instance. But if more than one servers are created, every server instance will have its own static variable, which will be reused by function invocations handled within the same server instance. This is still much better than creating a new connection for every invocation.

    Check out this detailed blog for performance load testing proofs of this as well.

  2. Use MemoryCache: This would allow you to share a cache between functions. For example:

    static MemoryCache memoryCache = MemoryCache.Default;
    
    
    public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
    {
        var cacheObject = memoryCache["cachedCount"];
        var cachedCount = (cacheObject == null) ? 0 : (int)cacheObject;   
        memoryCache.Set("cachedCount", ++cachedCount, DateTimeOffset.Now.AddMinutes(5));
    
        log.Info($"Webhook triggered memory count {cachedCount}");
        return ...
    }
    

    Here the code is trying to find the count in the cache, increment it, and save it with a five minute expiry. If we copy this same code to two functions within the same Azure Function App, then sure enough they each can see the count set by the other one. Note that, this cache will lose its contents every time you edit your code.

    Check out this blog for more details around this.

  3. Use Dependency Injection: Use DI to create Singleton instances and use them. Check out Use dependency injection in .NET Azure Functions. ServiceBusClient can be registered for dependency injection with the ServiceBusClientBuilderExtensions.

Note: The disposing of the static clients will be automatically done by .NET core runtime, if they implement IDisposable interface. Don't manually dispose it, otherwise it wont be reused. Further, ensure that the static clients are thread safe. As the MS Doc says:

Establishing a connection is an expensive operation that you can avoid by reusing the same factory and client objects for multiple operations. You can safely use these client objects for concurrent asynchronous operations and from multiple threads.

It is safe to instantiate once and share ServiceBusClient.

Additional links:

Let me know if you have any follow-up questions.

Upvotes: 3

Related Questions