Клиент отключен, потому что основной запрос был выполнен. Больше нет HttpContext - PullRequest
5 голосов
/ 01 июля 2019

Мы периодически получаем исключение The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available в нашей конечной точке WebApi.

Кто-нибудь знает, что является причиной этой ошибки или как ее можно последовательно воспроизвести?В настоящее время это происходит в 150 из 100 000 запросов.

Исключение выдается 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));

Таким образом, HttpBufferlessInputStream.Read () генерирует исключение после возврата wr.ReadEntityBody(buffer, offset, count)0 или отрицательный, а _context.Response.IsClientConnected - false.

Это будет означать, что клиент отключился, когда XmlDeserialize () все еще работал.Но из моих ограниченных экспериментов с netcat .NET ждет, пока весь XML-запрос не будет загружен, прежде чем даже вызвать метод контроллера.Таким образом, мы не загружаем запрос, пока еще десериализуем.

Ответы [ 2 ]

3 голосов
/ 04 июля 2019

Как это объяснено здесь вам следует избегать захвата контекста синхронизации и использовать .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;
    }
    ...
}

Как заметил Thowk , SynchronizationContext был удален из ASP.NET Core .

0 голосов
/ 08 июля 2019

Я думаю, что пустые данные или тайм-аут выполнения. Попробуйте захватить время и данные вызванного события и возвращенного вызова API. Попробуйте стресс-тестирование с консольным приложением. Проверьте журналы IIS или веб-сервера. Что касается вашего кода, это асинхронный метод добавить дополнительную строку

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

Напишите str в журнал и проверьте, какие данные были в нем. Попробуйте преобразовать его в метод синхронизации.

изменить время ожидания.

<system.web>
    <httpRuntime executionTimeout="180" />
</system.web>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...