HTTPClient间歇性锁定服务器

时间:2019-04-10 10:52:51

标签: asp.net-core dotnet-httpclient

我有一个.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);
                }
            }
        }
    }
}

编辑

因此修改了代码以删除用法,并直接以字符串形式而不是流方式返回代理响应,并且仍然遇到相同的问题。

运行netstat时,我确实看到很多代理API网址的日志。

4行提到要代理的API的IP,大概另外20行提到代理站点的IP。这些数字对我来说似乎并不奇怪,但我在使用netstat时没有太多经验(我第一次把它开除)。

我还让代理运行了大约20分钟。从技术上讲,它仍然有效。回应又回来了。从将API代理到返回数据与HttpClient解析之间只花了很长时间。但是,它不会处理任何新请求,它们只是挂在那儿。

0 个答案:

没有答案