我有带有2个HTTP触发函数的AzureFunctions应用程序。两者都从同一个类中删除,但是使用不同的url来获取数据。 每天Azure Data Factory管道都会触发第一个HTTP功能 而另一个管道在1分钟内调用了第二个功能
每个功能向第三方网站发出大约1300个HTTP请求,并将每个响应作为单独的json文件存储在Blob存储中。
问题几乎是每次(但并非总是)第二个函数引发System.Net.Sockets.SocketException,因为很少有出站请求遇到常见的21秒TCP超时。 我注意到的一件奇怪的事情-出于某种原因,我的出站请求可能会受到Azure限制:第一批耗时接近300ms,下一个序列耗时4.3秒,然后9.5秒,下一个批次达到21秒,例外
Here is image of timing increasing of outbound requests
异常堆栈跟踪:
System.Net.Http.HttpRequestException:连接尝试失败 因为关联方在一段时间后未正确响应 时间或建立的连接失败,因为连接的主机具有 无法响应---> System.Net.Sockets.SocketException:A 连接尝试失败,因为连接方未正确 一段时间后响应,或建立的连接失败 因为连接的主机无法响应 System.Net.Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口, CancellationToken cancellingToken)-内部异常结束 堆栈跟踪--- System.Net.Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口, 的CancellationToken cancelToken() System.Threading.Tasks.ValueTask
1.get_Result() at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask
1.get_Result()位于 System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask) at System.Threading.Tasks.ValueTask
1.get_Result()
在 System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request,布尔值doRequestAuth,CancellationToken cancelledToken)
在System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage 的请求,在 System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage 的请求,在 System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage请求,CancellationTokenSource cts,布尔值 disposeCts) FunctionApp.BaseFunc。<> c__DisplayClass7_2。d.MoveNext() 在 E:\ vsts-agent-win-1_work \ 339 \ s \ Services \ Host \ Controllers \ BaseFunc.cs:line 102 ---从上一个引发异常的位置开始的堆栈跟踪---在FunctionApp.BaseFunc.ProcessRun(ILogger log,String runId)在 E:\ vsts-agent-win-1_work \ 339 \ s \ Services \ Host \ Controllers \ BaseFunc.cs:line 122。
FunctionApp托管在AppService计划S1上,因此没有600的出站连接限制(我相信是这样)
异常期间TCP连接的度量(最大值为498): Metrics of AzureFunction App
AzureFunction App的“解决问题”助手的TCP连接 Max TCP connections in all states was 502
异常期间的CPU和应用程序内存服务计划: App Service Plan metrics
应用程序是.Net Core 2.2
我没有设法在本地PC上重现此内容。但是在Azure上,几乎每天都会在每种环境(开发,测试,生产)上发生这种情况。 失败之后,Azure数据工厂将在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);
}
}
}
}
功能代码本身:
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}");
}
}
}
感谢任何帮助。
答案 0 :(得分:0)
我也遇到了同样的问题,但就我而言,我有一个代码补丁,其中包含一个无限的while循环,该循环正在创建数百个对Microsoft GraphApi的请求,而没有响应一个请求,它正在创建另一个请求。我更正了,问题解决了!也许对某人有帮助