Azure Functions 中的 HttpClient 最佳实践

Posted

技术标签:

【中文标题】Azure Functions 中的 HttpClient 最佳实践【英文标题】:HttpClient best practices in Azure Functions 【发布时间】:2018-07-11 02:59:21 【问题描述】:

我需要构建一个 Azure 函数:

响应HTTP POST 请求 根据数据执行 7x HTTP HEAD 请求。

我找到了一些指导 here 和 here

但是,不完全清楚该做什么以及它是如何工作的?

与第二个链接一样,我目前刚刚声明了一个 private static HttpClient httpClient = new HttpClient(); 实例,并在我的 7x HTTP HEAD 调用中重新使用了它。

我的问题:

    这是在无状态 Azure 函数中最有效地使用 HttpClient 吗? 我目前正在为 http 调用建立一个 List<Task>(),然后对它们执行 Task.WhenAll(tasks) 以并行运行它们。这会是打这些电话的最快方法吗?还有其他建议吗?

这个 Function 端点会被大量调用(每秒多次),因此需要尽可能高效以降低成本。

谢谢!

【问题讨论】:

【参考方案1】:

从 2019 年开始,以及运行时的 v2/v3+,您还可以选择use dependency injection in .NET Azure Functions。请注意,这仅适用于 .NET 函数 (C#),而 AFAIK 不适用于其他风格,如 Python、javascript/TypeScript 等。

简单的答案是您可以将 Startup.cs 类添加到您注册依赖项的 Azure 函数中:

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

与任何其他具有 dotnet 核心的 web/api 项目几乎相同。接下来,在您的函数本身中,添加一个构造函数并将依赖项注册为参数。您还想从函数中删除 static 修饰符。一个例子:

public class MyInjectedFunction

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

通过使用 DI,您也可以将其显式注册为单例。或创建类型化的 HttpClients。就个人而言,我认为这很优雅。

【讨论】:

我在 Azure 文档中读到了这个,但不清楚它是如何在函数中创建 HttpClient 的。显然,Azure 函数有一个主机 DI 容器,它“保存”函数的每个请求实例,并将 HttpClient 作为单例提供给所有函数实例,因此在第一次配置后无法更改 BaseUri。那么,如果它实际上是一个单例并且无法修改,那么配置 HttpClient 的合适位置在哪里?【参考方案2】:

是的 - 这仍然是 Azure Functions 1.x(也适用于 2.x)的当前指南,以最好地避免套接字耗尽。静态变量将确保它将与类的所有实例共享。涵盖该主题的另一篇好文章是https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong

【讨论】:

谢谢。那篇文章是2016年的吗?最近没有什么表明它仍然是最好的方法吗?不是怀疑你,只是想确定:) 至少就 Azure Functions 的 1.x 和 .net 框架 4.x 而言,自 2016 年以来没有太大变化会影响指导 :) Azure Functions 2.x 虽然可能会引入一些新的选项\最佳实践,因为它位于 .net core 2.1 上。我怀疑该指南在很大程度上是相同的(最大限度地重用),但有一些新的与 httpclient 相关的结构,例如 HttpClientFactory (stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore),可能会引入一些新的或额外的选项\指南。 这个解决方案在一般情况下确实不是 HttpClient 的正确用法。持有一个实例也是错误的,因为 DNS 更改无法通过。您最终将失去所有连接。这就是存在 HttpClientFactory 的原因——但仅在 ASP .Net Core 2.1 中。我现在的问题是:我们现在应该做什么? @RPM1984 - 来自 Microsoft 的关于此 can be found here 的官方文档。然而,正如 Zordid 所提到的,如果你可以使用更新的 HttpClientFactory 那就更好了。

以上是关于Azure Functions 中的 HttpClient 最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Azure Functions 中的 HttpClient 最佳实践

Azure Functions 中的配置文件

Azure Functions 中的 DI

使用另一个项目中的 Azure Functions

如何从 Azure Functions 中的存储容器读取多个文件

Azure 事件中心 Event Grid(事件网格)+Azure Functions处理IOT Hub中的消息