通过 HTTP 调用 Azure Function 150 次导致异常

Posted

技术标签:

【中文标题】通过 HTTP 调用 Azure Function 150 次导致异常【英文标题】:Calling Azure Function 150 times by HTTP results in exception 【发布时间】:2017-12-14 02:56:28 【问题描述】:

我在 Azure 上运行一个 asp.net mvc Web 应用程序。在一种方法中,我对 Azure Function Web API 进行了多次 HTTP 调用。在此 Azure 函数中,我使用 DbContext 将新记录插入数据库。

// Method in web application making http requests to azure function web api
public async Task CreateRecords() 
    int amountOfCalls = 150;
    var allTasks = new List<Task<HttpResponseMessage>>();

    for (int i = 0; i < amountOfCalls; i++) 
        var task = HttpClientInstance.Instance.PostAsync(<uri>, new StringContent(i.ToString()));
        allTasks.Add(task);
    

    await Task.WhenAll(allTasks); // Gives an exception

amountOfCalls 设置为 25、50 或 100 时,一切正常。但是,当我将amountOfCalls设置为150时,最初它会向数据库中插入一些记录,但最终会导致错误:

无法连接到远程服务器。

所以首先我认为它必须是 Azure sql 数据库的最大并发登录数。所以我将那个升级到了定价层 S9(1600 个 DTU,最多 3200 个并发登录注意到here)。

但这并没有解决问题。于是我开始远程调试 Azure Function。并且它不会在 Azure 函数本身中给出异常。 因此,下一步是研究 Application Insights。我看到DbContext 的构造函数给出了异常(不幸的是没有堆栈跟踪):

类型:System.InvalidOperationException

方法:WebApp.DataAccess.PocDbContext..ctor

请求名称:InsertRecordFunction

请求持续时间:55,643.2201

Azure 函数如下所示:

[DependencyInjectionConfig(typeof(DependencyConfig))] // Autofac
public static class InsertRecordFunction

    [FunctionName("InsertRecordFunction")]
    public static async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "InsertRecordFunction")]HttpRequestMessage req,
        TraceWriter log,
        [Inject]IRecordDataService recordDataService)
    
        log.Info("InsertRecordFunction was triggered by Http.");
        try 
            await recordDataService.AddRandomRecordAsync();
        
        catch (Exception ex) 
            return req.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        
 
        return req.CreateResponse(HttpStatusCode.OK);
    

PocDbContext 的 ctor 看起来像这样:

public PocDbContext() : base("DefaultConnection") 
    Database.SetInitializer<PocDbContext>(null);

我仍然觉得它与 Azure sql 数据库的连接池有关。在这个问题之前,我遇到了另一个告诉我将执行策略设置为SqlAzureExecutionStrategy(我做到了this way)。

使用(静态)HttpClient 从 Azure Web App 调用 Web api 是否有某种最大值?我还能做些什么来找出确切的异常是什么?谢谢。

更新

在 Application Insights 中,我找到了有关异常的其他信息:

超时。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。

升级 Azure sql 数据库的定价层后,这不是我所期望的。

【问题讨论】:

一个线程在这里讨论可以在 azure 函数中处理的最大并发调用。 ***.com/questions/44257660/… 您可以检查有关此线程中提到的 maxconcurrent 请求。 github.com/Azure/Azure-Functions/issues/419 你能用队列代替http吗? @Baskar,这些链接并没有真正回答我的问题。 @Mikhail,我可以使用队列,但我只是在玩,发现我无法让它工作很奇怪。我确实在 Application Insights 中找到了内部异常:超时已过期。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。 连接字符串中Max Pool Size 的值是多少? 【参考方案1】:

来自支持实体框架 (SQL Server Connection Pooling (ADO.NET)) 的 ADO.NET 文档:

默认情况下,ADO.NET 中启用了连接池。除非您明确禁用它,否则池程序会在您的应用程序中打开和关闭连接时对其进行优化。

在Adding Connections 部分再往下一点:

根据需要将连接添加到池中,最大为指定的最大池大小(默认为 100)。

因此,将连接字符串的最大池大小明确设置为 >= 150 应该可以解决问题。

【讨论】:

以上是关于通过 HTTP 调用 Azure Function 150 次导致异常的主要内容,如果未能解决你的问题,请参考以下文章

尝试通过 Azure Function App 站点 URL 发布 ZIP 文件失败,HTTP 状态代码未经授权

使用 Azure Function 2.x 通过构造函数为 Http 触发函数注入 ILogger

Azure App Function (Functions 2.x):通过 HTTP 函数在 CosmosDB 中创建新文档

在 Azure Function 上使用 web3.js 调用 Ethereum

Azure Insights:通过函数执行链跟踪自定义属性

Azure Function App HTTP 触发来自请求正文的 CosmosDB 输入查询