Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpClient best practices in Azure Functions

I need to build an Azure Function that:

  • Responds to a HTTP POST request
  • Does 7x HTTP HEAD requests based on the data.

I've found some guidance here and here

But, it's not entirely clear what to do, and how it works?

As in the second link, i've currently just declared a private static HttpClient httpClient = new HttpClient(); instance, and re-used that in my 7x HTTP HEAD calls.

My questions:

  1. Is that the most efficient use of HttpClient in a stateless Azure function?
  2. I'm currently just building up a List<Task>() for the http calls, then doing Task.WhenAll(tasks) on them to run them in parrallel. Would that be the quickest way to do these calls? Any other suggestions?

This Function endpoint will be called a lot (multiple times a second), so need to be as efficient as possible to keep costs down.

Thanks!

like image 240
RPM1984 Avatar asked Jul 11 '18 02:07

RPM1984


People also ask

How do I use HttpClient in Azure function?

Instead of creating a new HttpClient instance(and other clients) every time a function is invoked, you should use a single HttpClient instance for all the calls. And the easiest way to implement it in Azure Functions is to declare the HttpClient as static outside of your Function's Run code.

What is the best practice to be followed in order to improve the performance of Azure function?

To reduce latency, create the storage account in the same region as the function app. To improve performance in production, use a separate storage account for each function app. This is especially true with Durable Functions and Event Hub triggered functions.

Why does Azure Functions need storage account?

Storage account requirements When creating a function app, you must create or link to a general-purpose Azure Storage account that supports Blob, Queue, and Table storage. This requirement exists because Functions relies on Azure Storage for operations such as managing triggers and logging function executions.

What is dependency injection in Azure?

Azure Functions supports the dependency injection (DI) software design pattern, which is a technique to achieve Inversion of Control (IoC) between classes and their dependencies. Dependency injection in Azure Functions is built on the . NET Core Dependency Injection features.


2 Answers

As of 2019, and v2/v3+ of the runtime, you also have the option to use dependency injection in .NET Azure Functions. Be aware that this only applies to .NET functions (C#), and AFAIK is not available for the other flavours, like Python, JavaScript/TypeScript etc.

Simple answer is that you can add a Startup.cs class to your Azure Function where your register the dependencies:

[assembly: FunctionsStartup(typeof(MyInjectedFunction.Startup))]

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Note: Only register dependencies, do not depend or request those in Configure().
        // Dependencies are only usable during function execution, not before (like here).
        
        builder.Services.AddHttpClient();
        // builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
    }
}

Pretty much the same as any other web/api project with dotnet core. Next, in your function itself, add a constructor and register the dependencies as parameters. You also want to remove the static modifier from your function. An example: ref :https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#register-services

public class MyInjectedFunction
{
    private readonly HttpClient _http;
    
    public MyInjectedFunction(IHttpClientFactory httpClientFactory)
    {
        _http = httpClientFactory.CreateClient();
    }
    
    [FunctionName("my-injected-function")]
    public async Task RunAsync([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
    {
        var response = await _http.GetAsync("https://stackoverflow.com");
        
        if (response.IsSuccessStatusCode)
            log.LogInformation("Okidoki");
        else
            log.LogError($"{response.StatusCode} {response.ReasonPhrase}: ");
    }
}

By using DI you can explicitly register it as singleton as well. Or created typed HttpClients. And personally, I think this is quite elegant.

like image 116
Juliën Avatar answered Sep 21 '22 07:09

Juliën


Yes - this is still the current guidance for Azure Functions 1.x (and applies to 2.x as well) to best avoid socket exhaustion. The static variable will ensures that it will be shared against all instances of the class. Another good article that covers this topic is https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong

like image 36
Josh Carlisle Avatar answered Sep 25 '22 07:09

Josh Carlisle