HTTPClient периодически блокирует сервер - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть приложение .NET Core 2.2, в котором есть контроллер, выступающий в качестве прокси для моих API.

JS делает выборку для прокси, прокси перенаправляет вызов API и возвращает ответ.

Я испытываю периодические блокировки прокси-приложения, когда оно ожидает ответа от HttpClient. Когда это происходит, он блокирует весь сервер. Больше запросов не будет обработано.

Согласно журналам API, который к нему подключается, возвращается нормально.

Чтобы воспроизвести это, я должен сделать 100+ запросов в цикле на клиенте через прокси. Затем я должен перезагрузить страницу несколько раз, перезагружая ее, пока 100 запросов находятся в полете. Обычно требуется около 5 ударов, прежде чем все начинает замедляться.

Прокси-сервер заблокируется в ожидании ожидаемого запроса на разрешение. Иногда он возвращается с задержкой в ​​4 - 5 секунд, иногда после менуэта. Большую часть времени я не ждал дольше 10 минут, прежде чем сдаться и убить прокси.

Я переместил код в следующий блок, который воспроизведет проблему.

Я полагаю, что я следую передовым методам, его асинхронность полностью снижена, я использую IHttpClientFactory, чтобы обеспечить совместное использование экземпляров HttpClient, я внедряю using там, где я считаю, что это требуется.

Реализация была основана на этом: https://github.com/aspnet/AspLabs/tree/master/src/Proxy

Я надеюсь, что я делаю довольно очевидную ошибку, что другие с большим опытом могут точно определить!

Любая помощь будет принята с благодарностью.


namespace Controllers
{
    [Route("/proxy")]
    public class ProxyController : Controller
    {
        private readonly IHttpClientFactory _factory;

        public ProxyController(IHttpClientFactory factory)
        {
            _factory = factory ?? throw new ArgumentNullException(nameof(factory));
        }

        [HttpGet]
        [Route("api")]
        async public Task ProxyApi(CancellationToken requestAborted)
        {
            // Build API specific URI
            var uri = new Uri("");

            // Get headers frpm request
            var headers = Request.Headers.ToDictionary(x => x.Key, y => y.Value);
            headers.Add(HeaderNames.Authorization, $"Bearer {await HttpContext.GetTokenAsync("access_token")}");

            // Build proxy request method. This is within a service
            var message = new HttpRequestMessage();

            foreach(var header in headers) {
                message.Headers.Add(header.Key, header.Value.ToArray());
            }

            message.RequestUri = uri;
            message.Headers.Host = uri.Authority;

            message.Method = new HttpMethod(Request.Method);

            requestAborted.ThrowIfCancellationRequested();

            // Generate client and issue request      
            using(message)
            using(var client = _factory.CreateClient())
            // **Always hangs here when it does hang**
            using(var result = await client.SendAsync(message, requestAborted).ConfigureAwait(false))
            {
                // Appy data from request onto response - Again this is within a service
                Response.StatusCode = (int)result.StatusCode;

                foreach (var header in result.Headers)
                {
                    Response.Headers[header.Key] = header.Value.ToArray();
                }

                // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response.
                Response.Headers.Remove("transfer-encoding");

                requestAborted.ThrowIfCancellationRequested();

                using (var responseStream = await result.Content.ReadAsStreamAsync())
                {
                    await responseStream.CopyToAsync(responseStream, 81920);
                }
            }
        }
    }
}

EDIT

Таким образом, код был изменен, чтобы удалить употребления и вернуть прокси-ответ непосредственно в виде строки вместо потоковой передачи и при этом получать те же проблемы.

При запуске netstat я вижу множество журналов для URL прокси-API.

В 4 строках указывается IP-адрес прокси-API, вероятно, еще в 20 строках указывается IP-адрес прокси-сайта. Эти цифры не кажутся мне странными, но у меня нет большого опыта использования netstat (впервые я его запустил).

Также я оставил прокси включенным около 20 минут. Это технически все еще жив. Ответы возвращаются. Прошло очень много времени между прокси API для возврата данных и разрешением HttpClient. Однако он не будет обслуживать любые новые запросы, они просто сидят и висят.

...