客户端已断开连接,因为基础请求已完成。不再有HttpContext可用

时间:2019-07-01 09:17:56

标签: c# asp.net-web-api

我们在WebApi端点中间歇性地收到The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available异常。

是否有人知道导致此错误的原因,或者如何以一致的方式重现该错误?目前,它发生在100,000个请求中的150个中。

XmlDeserialize()在此部分代码中引发了异常:

[HttpPost]
public async Task<IHttpActionResult> Process()
{
    using (var requestStream = await Request.Content.ReadAsStreamAsync())
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));

        // !! The below line throws the exception
        MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
    }
    ...
}

这是完整的异常消息:

  "ExceptionType": "HttpException",
  "Message": "The client is disconnected because the underlying request has been completed.  There is no longer an HttpContext available.",
  "StackTrace": [
    "HttpBufferlessInputStream.Read;0",
    "SeekableBufferedRequestStream.Read;0",
    "XmlTextReaderImpl.ReadData;0",
    ...

编辑:我在.NET的源代码中找到了它。 System.Web.txt

HttpBufferlessInputStream_ClientDisconnected=The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available.

https://referencesource.microsoft.com/#system.web/HttpBufferlessInputStream.cs,332ecbede7a1f12a

// We are done if the count == 0 or there is no more content
while (count > 0 && _remainingBytes != 0) {
    // Do the actual read
    bytesRead = wr.ReadEntityBody(buffer, offset, count);
    if (bytesRead <= 0) {
        if (!_context.Response.IsClientConnected) {
            if (_persistEntityBody) {
                SetRawContentOnce();
            }
            throw new HttpException(SR.GetString(SR.HttpBufferlessInputStream_ClientDisconnected));

因此,在wr.ReadEntityBody(buffer, offset, count)返回0或负数并且_context.Response.IsClientConnected为false之后,HttpBufferlessInputStream.Read()会引发异常。

这意味着XmlDeserialize()仍在运行时,客户端已断开连接。但是根据我对netcat的有限实验,.NET一直等到整个XML请求都已上传,甚至没有调用controller方法。因此,我们在反序列化时就不会上传请求。

2 个答案:

答案 0 :(得分:3)

就像已经解释过的here一样,您应该避免捕获同步上下文并使用.ConfigureAwait(false);

[HttpPost]
public async Task<IHttpActionResult> Process()
{
    using (var requestStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));
        MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
    }
    ...
}

ThowkSynchronizationContext has been removed from ASP.NET Core注意到了。

答案 1 :(得分:0)

我认为其为空数据或执行超时问题。尝试捕获事件的时间和数据以及返回的api调用的数据。尝试使用控制台应用程序进行一些压力测试。 检查您的IIS或Web服务器日志。 关于您的代码的异步方法  添加多余的行

string str = response.Content.ReadAsStringAsync().Result;

编写str进行记录并检查其中包含什么数据。 尝试将其转换为同步方法。

更改您的超时时间。

<system.web>
    <httpRuntime executionTimeout="180" />
</system.web>