gpt4 book ai didi

c# - ASP.NET Core 对 Azure 应用服务的缓慢 HTTP 请求

转载 作者:太空宇宙 更新时间:2023-11-03 12:00:34 25 4
gpt4 key购买 nike

我有一个 ASP.NET Core 中间件调用另一个 HTTP 服务来检查用户是否有权继续请求。目前它取决于提供的自定义 header ,称为 X-Parameter-Id

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;

namespace ParameterAuthorization.Middleware
{
public class ParameterAuthorizationMiddleware
{
private readonly RequestDelegate _next;
private readonly IParameterAuthorizationService _parameterAuthorizationService;

public ParameterAuthorizationMiddleware(RequestDelegate next, IParameterAuthorizationService parameterAuthorizationService)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_parameterAuthorizationService = parameterAuthorizationService ?? throw new ArgumentNullException(nameof(parameterAuthorizationService));
}

public async Task InvokeAsync(HttpContext httpContext, IConfiguration configuration)
{
if (httpContext is null)
{
throw new ArgumentNullException(nameof(httpContext));
}

if (parameterRequestContext is null)
{
throw new ArgumentNullException(nameof(parameterRequestContext));
}

if (!(httpContext.Request.Headers.ContainsKey("X-Parameter-Id") && httpContext.Request.Headers.ContainsKey("Authorization")))
{
await ForbiddenResponseAsync(httpContext);
}

var parameterIdHeader = httpContext.Request.Headers["X-Parameter-Id"].ToString();

if (!int.TryParse(parameterIdHeader, out var parameterId) || parameterId < 1)
{
await ForbiddenResponseAsync(httpContext);
}

var authorizationHeader = httpContext.Request.Headers["Authorization"].ToString();

var parameterResponse = await _parameterAuthorizationService.AuthorizeUserParameterAsync(parameterId, authorizationHeader);

if (string.IsNullOrWhiteSpace(parameterResponse))
{
await ForbiddenResponseAsync(httpContext);
}

await _next.Invoke(httpContext);
}

private static async Task ForbiddenResponseAsync(HttpContext httpContext)
{
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
await httpContext.Response.WriteAsync("Forbidden");
return;
}
}
}

这就是 HTTP 调用实现:

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace ParameterAuthorization.Middleware.Http
{
public class ParameterAuthorizationService : IParameterAuthorizationService
{
private readonly HttpClient _httpClient;
private readonly JsonSerializer _jsonSerializer;

public ParameterAuthorizationService(HttpClient httpClient, JsonSerializer jsonSerializer)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
_jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
}

public async Task<string> AuthorizeUserParameterAsync(int parameterId, string authorizationHeader)
{
var request = CreateRequest(parameterId, authorizationHeader);

var result = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

if (!result.IsSuccessStatusCode)
{
return string.Empty;
}

using (var responseStream = await result.Content.ReadAsStreamAsync())
using (var streamReader = new StreamReader(responseStream))
using (var jsonTextReader = new JsonTextReader(streamReader))
{
return _jsonSerializer.Deserialize<ParameterResponse>(jsonTextReader).StringImInterestedIn;
}
}

private static HttpRequestMessage CreateRequest(int parameterId, string authorizationHead1er)
{
var parameterUri = new Uri($"parameters/{parameterId}", UriKind.Relative);

var message = new HttpRequestMessage(HttpMethod.Get, parameterUri);

message.Headers.Add("Authorization", authorizationHead1er);

return message;
}
}
}

这是名为 HttpClient 的 DI 的样板代码

sc.TryAddSingleton<JsonSerializer>();
sc.AddHttpClient<IParameterAuthorizationService, ParameterAuthorizationService>(client =>
{
client.BaseAddress = authorizationServiceUri;
client.DefaultRequestHeaders.Add("Accept", "application/json");
});

authorizationServiceUri 是我通过自定义扩展方法提供的内容。

问题是我对该服务的调用会随机花费 7 秒、10 秒甚至 20 秒,然后它会变得很快,然后又变慢。我从 Postman 中调用这个确切的 ParameterAuthorizationService,持续不到 50 毫秒。

我附上了 Application Insights 的屏幕截图,显示了整个事件序列。

Application Insights performance log

这两种服务都作为 Azure 应用服务部署在同一应用服务计划的同一订阅下。

代码工作得很好,但我已经抓狂了,不知道是什么导致了这些性能异常。

我还检查了 Azure 应用服务中的 TCP 连接,它都是绿色的。

TCP Connections

某些 HTTP 调用真的很慢的原因可能是什么?

更新

我的应用服务在 S1 应用服务计划上运行。 https://azure.microsoft.com/en-us/pricing/details/app-service/windows/

最佳答案

如果您写入 httpContent,您应该将管道短路。参见 Aspnet Core Middleware documentation :

Don't call next.Invoke after the response has been sent to the client.

使用这样的东西:

if (string.IsNullOrWhiteSpace(parameterResponse))
{
await ForbiddenResponseAsync(httpContext);
}
else
{
await _next.Invoke(httpContext);
}

还考虑使用从 aspnet 核心继承的中间件处理身份验证 AuthenticationHandler类以利用所有 aspnet 核心身份验证/授权设施。这是一个 BasicAuthentification handler 的实现示例为简单起见。

您的 ParameterAuthorizationService 看起来不错。我不认为这是您缓慢请求调用的来源。可以肯定的是,您可以 track the entire service call通过测量花费的时间并在 appinsights 中发布:

public class ParameterAuthorizationService : IParameterAuthorizationService
{
//...

private readonly TelemetryClient _telemetryClient;

public ParameterAuthorizationService(HttpClient httpClient, JsonSerializer jsonSerializer)
{
//...

_telemetryClient = new TelemetryClient();
}

public async Task<string> AuthorizeUserParameterAsync(int parameterId, string authorizationHeader)
{
var startTime = DateTime.UtcNow;
var timer = Stopwatch.StartNew();
var isSuccess = true;

try
{
return await AuthorizeUserParameterImpl(parameterId, authorizationHeader);
}
catch (Exception ex)
{
timer.Stop();
isSuccess = false;

_telemetryClient.TrackException(ex);
_telemetryClient.TrackDependency("Http", nameof(ParameterAuthorizationService), nameof(AuthorizeUserParameterAsync),
startTime, timer.Elapsed, isSuccess);
throw;
}
finally
{
if (timer.IsRunning)
timer.Stop();
if (isSuccess)
_telemetryClient.TrackDependency(
"Http", nameof(ParameterAuthorizationService), nameof(AuthorizeUserParameterAsync),
startTime, timer.Elapsed, isSuccess);
}
}

private async Task<string> AuthorizeUserParameterImpl(int parameterId, string authorizationHeader)
{
//Your original code
}
}

关于c# - ASP.NET Core 对 Azure 应用服务的缓慢 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57225809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com