C# Azure函数运行到System.Net.Sockets.SocketException中
我有一个AzureFunctions应用程序,有两个HTTP触发函数。两者都来自同一个类,但使用不同的URL获取数据。 每天Azure Data Factory管道都会触发第一个HTTP函数 另一条管道在1分钟内调用第二个函数 每个函数向第三方网站发出大约1300个HTTP请求,并将每个响应作为单独的json文件存储在Blob存储中 问题几乎每次(但并非总是)第二个函数抛出System.Net.Sockets.SocketException时都会出现,因为很少有出站请求会运行到常见的21秒TCP超时。 我注意到了一件奇怪的事情——可能是Azure出于某种原因限制了我的出站请求:第一批需要大约300毫秒,下一批需要4.3秒,然后是9.5秒,下一批需要21秒 异常堆栈跟踪: System.Net.Http.HttpRequestException:连接尝试失败 因为关联方在一段时间后未作出适当回应 时间,或建立的连接失败,因为连接的主机已 未能响应-->System.Net.Sockets.SocketException:A 连接尝试失败,因为连接方未正确连接 一段时间后响应,或建立的连接失败 因为连接的主机无法在响应 System.Net.Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口, CancellationToken CancellationToken)--内部异常结束 堆栈跟踪--at System.Net.Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口, 取消令牌(取消令牌)位于 System.Threading.Tasks.ValueTaskC# Azure函数运行到System.Net.Sockets.SocketException中,c#,asp.net-core,azure-functions,tcpclient,socketexception,C#,Asp.net Core,Azure Functions,Tcpclient,Socketexception,我有一个AzureFunctions应用程序,有两个HTTP触发函数。两者都来自同一个类,但使用不同的URL获取数据。 每天Azure Data Factory管道都会触发第一个HTTP函数 另一条管道在1分钟内调用第二个函数 每个函数向第三方网站发出大约1300个HTTP请求,并将每个响应作为单独的json文件存储在Blob存储中 问题几乎每次(但并非总是)第二个函数抛出System.Net.Sockets.SocketException时都会出现,因为很少有出站请求会运行到常见的21秒TCP
1.get_Result()位于
System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage
请求,取消令牌(取消令牌)位于
System.Threading.Tasks.ValueTask
1.获取结果()位于
System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1
creationTask)在System.Threading.Tasks.ValueTask
1.get_Result()在 System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage 请求,布尔值doRequestAuth,CancellationToken CancellationToken)
在System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage 请求,取消令牌(取消令牌)位于 System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage 请求,取消令牌(取消令牌)位于 System.Net.Http.HttpClient.FinishSendAsyncBuffered(任务'1 sendTask, HttpRequestMessage请求,CancellationTokenSource cts,布尔值 处置)在 FunctionApp.BaseFunc.c_uudisplayClass7_2.d.MoveNext() 在里面 E:\vsts-agent-win-1\u work\339\s\Services\Host\Controllers\BaseFunc.cs:line 102 ---来自引发异常的上一个位置的堆栈结束跟踪——在functionpp.BaseFunc.ProcessRun(ILogger 日志,字符串(runId) E:\vsts-agent-win-1\u work\339\s\Services\Host\Controllers\BaseFunc.cs:line 122 FunctionApp托管在AppService plan S1上,因此出站连接没有600个的限制(我相信是这样) 异常期间TCP连接的度量(最大值为498): 来自AzureFunction应用程序“解决问题”助手的TCP连接 异常期间应用程序服务计划的CPU和内存: 应用程序是.Net核心2.2 我没有在我的本地PC上复制它。但是在Azure上,它几乎每天都在每个环境(开发、测试、产品)上发生。 失败后,Azure Data Factory在5分钟内重试,每次都成功 下面是两个函数使用的基类代码:
public abstract class BaseFunc
{
protected abstract string BlobFolderName { get; }
protected TelemetryClient telemetryClient;
private static HttpClient _httpClient;
static BaseFunc()
{
HttpClientHandler handler = new HttpClientHandler();
handler.MaxConnectionsPerServer = 300;
_httpClient = new HttpClient(handler);
}
protected async Task ProcessRun(ILogger log, string runId)
{
int processedItems = 0;
try
{
Stopwatch sw = Stopwatch.StartNew();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
await Authentication("url", log, runId); //sets default Authorization header
string getIdeaResult = await _httpClient.GetStringAsync("url");
JObject jsonObject = JObject.Parse(getIdeaResult);
int ideaCount = (int)jsonObject.SelectToken("total_count");
List<Task> tasks = new List<Task>();
string DataPulledDate = DateTime.Now.ToString("dd-MMM-yyyy");
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("connection string");
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("container");
string getIdsUri = "url" + $"&limit={batchSize}&offset=";
int iterations = (int)Math.Ceiling((decimal)ideaCount/batchSize);
for (int i = 0; i < iterations; i++)
{
string result = await _httpClient.GetStringAsync("url" + i * 50);
JObject jsonIdsObject = JObject.Parse(result);
int[] ideaIds = jsonIdsObject["content"].Children().Values<int>("id").ToArray();
foreach (int id in ideaIds)
{
tasks.Add(Task.Run(async () =>
{
string content = null;
using (var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "url"+ id))) //Exception is thrown on this line
{
content = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
}
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference($"{DataPulledDate}/{BlobFolderName}/ideaId-{id}.json");
await cloudBlobContainer.CreateIfNotExistsAsync();
await cloudBlockBlob.UploadTextAsync(content);
Interlocked.Increment(ref processedItems);
}));
}
}
await Task.WhenAll(tasks);
sw.Stop();
}
catch (Exception ex)
{
log.LogError(ex, "{RunId}: Run failed. {Items} items processed successfully, Exception: {Exception}.", runId, processedItems, ex.ToString());
throw;
}
finally
{
if (telemetryClient != null)
{
telemetryClient.Flush();
Thread.Sleep(3000);
}
}
}
}
感谢您的帮助。我们也遇到了同样的问题,但在我们的案例中,我们有一个代码修补程序,它有一个无限的while循环,创建了数百个对Microsoft GraphApi的请求,而没有响应一个请求,它创建了另一个请求。我们纠正了它,问题解决了!也许这对某人有帮助您是否为每个连接创建了一个新的
BaseFunc
@谢谢你的回复。没有-在初始问题中添加函数代码您多久创建一次新的GetIdeas?如果是每次“呼叫”一次,那么你就与我发布的链接不符。@Neil我没有实例化GetIdeas。它是Azure函数的入口点。这类似于使用“始终打开”设置运行的WebJob。因此,我们应该始终运行。“Run”由Http调用从外部调用抱歉,我错过了BaseFunc
构造函数上的static
。
namespace FunctionApp
{
public class GetIdeas : BaseFunc
{
public GetIdeas(TelemetryClient telemetryClient)
{
this.telemetryClient = telemetryClient;
}
protected override string BlobFolderName { get => "folder"; }
protected override string GetItemUrl { get => "url"; }
[FunctionName("GetIdeasFn")]
public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log)
{
await ProcessRun(log, $"GetIdeasFn - {DateTime.UtcNow.Ticks}");
}
}
}