У меня проблема ниже при звонке api/Values/Test?times={x}
.Эта проблема не возникает, когда x
равен 1, 2, ..., но веб-запрос истекает, когда он достигает 9, 10 и т. Д.Как видите, конечная точка Test
будет отправлять веб-запрос EndPoint
x
раз (извините за бессмысленные тела методов, они на практике будут делать более значимые вещи):
public class ValuesController: System.Web.Http.ApiController
{
[HttpGet]
public async Task<object> Test(int times)
{
var tasks = new List<Task<int>>();
for (var i = 0; i < times; i++)
{
//Make web request to the `EndPoint` method below
var task = new ApiRequestBuilder<int>("https://localhost:44301/api/Values/EndPoint")
.GetAsync();
tasks.Add(task);
}
return await Task.WhenAll(tasks.ToArray());
}
[HttpGet]
[CustomAuthorise]//This makes a web request to `AuthEndPoint` (below)
public int EndPoint()
{
return 0;
}
[HttpGet]
public bool AuthEndPoint()
{
return true;
}
}
( NB см. Ниже, что такое ApiRequestBuilder
)
Проблема, однако, заключается не в том, что EndPoint
ударяют x
раз, а в атрибуте CustomAuthorise
, который делаетследующий веб-запрос - вот проблема:
public class CustomAuthoriseAttribute : System.Web.Http.AuthorizeAttribute
{
public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
var result = await this.AuthoriseAsync(actionContext);
if (!result)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
}
}
public virtual async Task<bool> AuthoriseAsync(HttpActionContext context)
{
//***********HANGING HERE************
//var result= await new ApiRequestBuilder<bool>("https://www.example.com")
var result= await new ApiRequestBuilder<bool>("https://localhost:44301/Values/AuthEndPoint")
.GetAsync();
return result;
}
}
Как видите, я закомментировал маршрут "https://www.example.com"
.Когда я задаю URL-адрес, который не является localhost
, веб-запрос может спамить (путем установки x
на большое число), сколько бы я ни хотел.
ApiRequestBuilder
- это помощник для создания веб-запросов через System.Net.Http.HttpClient
(версия 4.0.0.0
, .NETframework v4.5.1
), который сериализует ответ на заданный вами параметр универсального типа.
public class ApiRequestBuilder<T>
{
protected string Url => Uri?.AbsoluteUri;
protected Uri Uri;
protected readonly HttpClient Client;
public ApiRequestBuilder(string url)
{
Uri = new Uri(url);
var client = new HttpClient()
{
BaseAddress = this.Uri,
//Set timeout so replicating this issue itn't a pain
Timeout = TimeSpan.FromSeconds(5)
};
this.Client = client;
}
public async Task<T> GetAsync()
{
var response = await this.Client.GetAsync(this.Url);
var responseContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseContent);
}
}
Вещи, которые я пробовал:
Имеют оператор using
для каждого использования HttpClient
в ApiRequestBuilder
- все еще зависает.
Ожидайте каждый Task
в цикле for в ValuesController.Test
- это работает, но не решает мою проблему, так как на практике я пытаюсь симулировать параллелизм для использования моего пользовательского атрибута auth.
Потенциально полезно:
Я использую локальный IIS на порту 44301
, максимальное количество одновременных подключений велико - 4294967295.
Как я уже сказал, изменение URL-адреса с localhost
на что-то вроде example.com
при авторизации устраняет проблему, которая изолирует проблему от того, что что-то не так с моей локальной настройкой
Кто-нибудь знает, почему использование веб-запроса в атрибутах авторизации кажется зависшим при одновременном использовании?g localhost
вместо того, чтобы использовать URL в большом мире?
ОБНОВЛЕНИЕ
Запуск netstat -n
в точке зависания (я удалил тайм-аутдля этого, чтобы я мог посмотреть, что делают соединения TCP).Для каждого выполняемого веб-запроса, который, казалось бы, был заблокирован, у меня было следующее:
Proto Local Address Foreign Address State
TCP [::1]:44301 [::1]:44728 CLOSE_WAIT
TCP [::1]:44728 [::1]:44301 FIN_WAIT_2
С помощью this создается впечатление, что сервер попросил клиента выйти, клиентыпризнал это, но они оба зависают (клиент не закрывается?).