Я не ищу альтернативы потоковой передачи содержимого файла из
база данных, действительно я ищу корень проблемы, это было
запустить файл до IIS 6, где мы запустили наше приложение в классическом режиме, теперь мы
обновил IIS до 7, и мы запускаем пул приложений в режиме конвейера и
эта проблема началась.
У меня есть обработчик, где я должен доставлять большие файлы по запросу клиента. И я сталкиваюсь со следующими проблемами,
Файлы имеют средний размер от 4 до 100 МБ, поэтому давайте рассмотрим случай загрузки файла размером 80 МБ.
Буферизация включена, медленный запуск
Response.BufferOutput = True;
Это приводит к очень медленному запуску файла, поскольку пользовательские загрузки и даже индикатор выполнения не отображаются в течение нескольких секунд, обычно от 3 до 20 секунд, причина в том, что IIS сначала читает весь файл, определяет длину содержимого, а затем начинает передача файла. Файл воспроизводится в видеоплеере и работает очень медленно, однако iPad сначала загружает только часть файла, поэтому он работает быстро.
Буферизация выключена, нет длины контента, быстрый запуск, нет прогресса
Reponse.BufferOutput = False;
Это приводит к немедленному запуску, однако конечный клиент (типичный браузер, такой как Chrome) не знает Content-Length, поскольку IIS тоже не знает, поэтому он не отображает ход выполнения, вместо этого он сообщает, что загружено X KB.
Отключение буферизации, длина содержимого вручную, быстрый запуск, выполнение и нарушение протокола
Response.BufferOutput = False;
Response.AddHeader("Content-Length", file.Length);
Это приводит к правильной немедленной загрузке файлов в Chrome и т. Д., Однако в некоторых случаях обработчик IIS приводит к ошибке «Закрытое подключение удаленного клиента» (это очень часто), а другие WebClient приводят к нарушению протокола. Это происходит от 5 до 10% всех запросов, а не всех запросов.
Полагаю, что происходит, IIS не отправляет ничего с именем 100 continue, когда мы не выполняем буферизацию, и клиент может отключиться, не ожидая какого-либо вывода. Однако чтение файлов из источника может занять больше времени, но на стороне клиента я увеличил время ожидания, но похоже на время ожидания IIS и не могу его контролировать.
Могу ли я в любом случае принудительно заставить Response отправить 100, чтобы никто не закрыл соединение?
UPDATE
Я обнаружил следующие заголовки в Firefox / Chrome, здесь нет ничего необычного для нарушения протокола или плохого заголовка.
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
Cache-Control:private
Content-Disposition:attachment; filename="24.jpg"
Content-Length:22355
Content-Type:image/pjpeg
Date:Wed, 07 Mar 2012 13:40:26 GMT
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
ОБНОВЛЕНИЕ 2
Включение рециркуляции по-прежнему мало что дает, но я увеличил свой MaxWorkerProcess до 8, и теперь я получаю меньше ошибок, чем раньше.
Но в среднем из 200 запросов в секунду от 2 до 10 запросов завершаются неудачно ... и это происходит почти каждые две секунды.
ОБНОВЛЕНИЕ 3
Продолжая 5% сбоев запросов с «Сервер совершил нарушение протокола. Section = ResponseStatusLine», у меня есть другая программа, которая загружает контент с веб-сервера, который использует WebClient, и который выдает эту ошибку 4-5 раз в секунду, на в среднем у меня 5% запросов не выполняются. Есть ли способ отследить сбой WebClient?
Переопределенные проблемы
Получен нулевой байт файл
IIS по какой-то причине закрывает соединение, на стороне клиента в WebConfig я получаю 0 байт для файла, который не является нулевым байтом, мы выполняем проверку хэша SHA1, это говорит нам о том, что на веб-сервере IIS ошибка не записывается.
Это была моя ошибка, и она была устранена, так как мы использовали Entity Framework, она считывала грязные (незафиксированные строки), так как считывание не входило в область транзакции, а помещение ее в область транзакции решило эту проблему.
Возникло исключение нарушения протокола
WebClient выдает WebException, говоря: «Сервер совершил нарушение протокола. Section = ResponseStatusLine.
Я знаю, что могу включить небезопасный разбор заголовков, но это не главное, когда мой HTTP-обработчик отправляет правильные заголовки, не знаю, почему IIS отправляет что-то дополнительное (проверено на firefox и chrome, ничего необычного), этопроисходит только 2% раз.
ОБНОВЛЕНИЕ 4
Обнаружена ошибка sc-win32 64, и я где-то читал, что WebLimits для MinBytesPerSecond должен быть изменен с 240 на 0, но все жевсе одинаково.Однако я заметил, что всякий раз, когда IIS регистрирует ошибку 64 sc-win32, IIS записывает HTTP Status как 200, но при этом возникает некоторая ошибка.Теперь я не могу включить ведение журнала Failed Trace Logging для 200, потому что это приведет к массивным файлам.
Обе вышеуказанные проблемы были решены путем увеличения MinBytesPerSecond, а также отключения сеансов. Я добавил подробный ответ, обобщающий каждыйбалл.