Azure 函数异常 - 将日志写入表存储时出错:Microsoft.Azure.Cosmos.Table.StorageException

Mic*_*Mic 5 c# azure .net-core azure-blob-storage azure-cosmosdb

我有一个 azure 函数,它与 blob 存储通信以读取上次同步日期时间,然后基于此从 Cosmos 数据库中读取数据。

很少有交互可以正常工作,并且在某些情况下会随机抛出以下异常

“将日志写入表存储时出错:Microsoft.Azure.Cosmos.Table.StorageException:无法执行套接字上的操作,因为系统缺乏足够的缓冲区空间或队列已满。 ---> System.Net.Http .HttpRequestException: 无法执行套接字上的操作,因为系统缺乏足够的缓冲区空间或队列已满。 ---> System.Net.Sockets.SocketException (10055): 无法执行套接字上的操作因为系统缺乏足够的缓冲区空间或因为队列已满。在 System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken CancellationToken) --- 内部异常堆栈跟踪结束 --- 在 System.Net .Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口,CancellationTokencancellationToken)在System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage请求,布尔allowHttp2,CancellationTokencancellationToken)在System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage请求, CancellationToken CancellationToken) 在 System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken CancellationToken) 在 System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken CancellationToken) 在 System.Net.Http.RedirectHandler.SendAsync (HttpRequestMessage 请求,CancellationToken CancellationToken)在 System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage 请求,CancellationToken CancellationToken)在 System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(任务1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at Microsoft.Azure.Cosmos.Table.RestExecutor.TableCommand.Executor.ExecuteAsync[T](RESTCommand1 cmd,IRetryPolicy 策略,OperationContext operationContext,CancellationToken 令牌)-- - 内部异常堆栈跟踪结束 ---1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token) at Microsoft.Azure.WebJobs.Logging.Utility.SafeExecuteAsync(CloudTable table, TableBatchOperation batch) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Logging\Internal\Utility.cs:line 178 at Microsoft.Azure.WebJobs.Logging.Utility.WriteBatchAsync[T](ILogTableProvider logTableProvider, IEnumerable位于 C:\projects\azure-webjobs-sdk-rqm4t\src\ 中的 Microsoft.Azure.Cosmos.Table.RestExecutor.TableCommand.Executor.ExecuteAsync[T](RESTCommand 1 e1) Microsoft.Azure.WebJobs.Logging\Internal\Utility.cs:位于 C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft 中 Microsoft.Azure.WebJobs.Logging.LogWriter.FlushTimelineAggregateAsync(始终为布尔值)的第 268 行。 Azure.WebJobs.Logging\Internal\LogWriter.cs:C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs 中 Microsoft.Azure.WebJobs.Logging.LogWriter.FlushCoreAsync() 的第 265 行。 Logging\Internal\LogWriter.cs:第 316 行请求信息 RequestID: RequestDate: StatusMessage: ErrorCode:"

任何人都可以告诉我如何修复它吗?

Zha*_*uid 5

我刚刚从 v2 升级到 v3 的函数应用程序遇到了同样的问题。

正如您所注意到的,异常不是来自您的代码,而是来自 内部Microsoft.Azure.WebJobs.Logging,无论您在做什么,它都只是继续做自己的事情。它也只发生在本地,而不是在我部署的实例中。

根据此处的答案,我从文件中删除了AzureWebJobsDashboardlocal.settings.json设置,并且错误已消失。

AzureWebJobsDashboard如果设置了应用程序设置,内部函数将使用表存储进行日志记录。建议使用 Application Insights 登录生产场景,这样您就可以安全地删除它并设置APPINSIGHTS_INSTRUMENTATIONKEY应用程序设置。

因为我不需要为本地开发存储日志,并且我部署的功能都只有该APPINSIGHTS_INSTRUMENTATIONKEY集。


kri*_*shg 3

由于您没有分享函数中的任何相关代码,因此我的回答有点笼统。这似乎是由于套接字耗尽问题造成的。虽然github 上有一个不确定的类似问题有更多细节,但有一些很好的建议可以消除任何容易实现的成果(我强烈建议您阅读):

我特别建议您确保 Cosmos(或 Table)客户端、HttpClient 等在静态私有实例外部方法中的共享连接重用。

静态客户端

为了避免持有不必要的连接,请重用客户端实例,而不是在每次函数调用时创建新的客户端实例。我们建议重复使用您编写函数所用的任何语言的客户端连接。例如, 如果您使用单个静态客户端,则HttpClientDocumentClient和 Azure 存储客户端等 .NET 客户端可以管理连接。

以下是在 Azure Functions 应用程序中使用特定于服务的客户端时需要遵循的一些准则:

  • 不要在每次函数调用时都创建一个新客户端。
  • 创建一个每个函数调用都可以使用的单个静态客户端。
  • 如果不同的函数使用相同的服务,请考虑在共享帮助程序类中创建单个静态客户端。

例子:

using Microsoft.Azure.Documents.Client;

private static Lazy<DocumentClient> lazyClient = new Lazy<DocumentClient>(InitializeDocumentClient);
private static DocumentClient documentClient => lazyClient.Value;

private static DocumentClient InitializeDocumentClient()
{
    // Perform any initialization here
    var uri = new Uri("example");
    var authKey = "authKey";
    
    return new DocumentClient(uri, authKey);
}

// Function
public static async Task Run(string input)
{
    Uri collectionUri = UriFactory.CreateDocumentCollectionUri("database", "collection");
    object document = new { Data = "example" };
    await documentClient.UpsertDocumentAsync(collectionUri, document);
    
    // Rest of function
}
Run Code Online (Sandbox Code Playgroud)