ASP.NET, IIS / CLR Поток и запрос относительно синхронного и асинхронного программирования - PullRequest
9 голосов
/ 09 сентября 2011

Я просто пытаюсь прояснить некоторые понятия здесь.Если кто-то готов поделиться своим опытом в этом вопросе, он будет признателен за это.

Вот мое понимание того, как IIS работает с потоками, пожалуйста, исправьте меня, если я ошибаюсь.

HTTP.sys

Насколько я понимаю, для IIS 6.0 (пока я оставлю IIS 7.0) веб-браузер делает запрос, получает драйвер ядра HTTP.sys,HTTP.sys передает его в пул потоков IIS 6.0 (поток ввода-вывода?), И он освобождается сам.

IIS 6.0 Thread / ThreadPool

Поток IIS 6.0 возвращает его в ASP.NET, который возвращает временный HSE_STATUS_PENDING в IIS 6.0, что освобождает поток IIS 6.0, а затемперешлите его в ветку CLR.

CLR Thread / ThreadPool

Когда ASP.NET выбирает свободный поток в пуле потоков CLR, он выполняет запрос.Если нет доступных потоков CLR, он помещается в очередь в очереди уровня приложения (которая имеет плохую производительность)

Итак, исходя из предыдущего понимания, у меня следующие вопросы.

  1. В синхронном режиме это означает 1 запрос на 1 поток CLR?

    *) Если это так, сколько запросов CONCURRENT можно обслуживать на 1 процессоре?Или я должен спросить обратное?Как разрешить потоки CLR на 1 процессор?Скажем, разрешено 50 потоков CLR. Значит ли это, что в любой момент времени ограничено обслуживать 50 запросов?Смущенный.

  2. Если я установлю «requestQueueLimit» в конфигурации «processModle» на 5000, что это означает на самом деле?Вы можете поставить в очередь до 5000 запросов в очереди приложений?Разве это не плохо?Зачем вам устанавливать его так высоко, поскольку очередь приложений имеет плохую производительность?

  3. Если вы программируете асинхронную страницу, где именно она начинает получать выгоду в вышеописанном процессе?

  4. Я исследовал и вижу, что по умолчанию размер пула потоков IIS 6.0 равен 256. Поступает 5000 одновременных запросов, которые обрабатываются 256 потоками IIS 6.0, а затем каждым из 256 потоков рукамиэто к потокам CLR, которые, я предполагаю, еще ниже по умолчанию.разве это не асинхронно?Немного смущен.Кроме того, где и когда узкое место начинает проявляться в синхронном режиме?а в асинхронном режиме?(Не уверен, что я что-то понимаю, я просто запутался).

  5. Что происходит, когда пул потоков IIS (все 256 из них) занят?

  6. Что происходит, когда все потоки CLR заняты?(Полагаю, тогда все запросы помещаются в очередь в очереди уровня приложения)

  7. Что происходит, когда очередь приложения находится над requestQueueLimit?

Большое спасибо за чтение, очень ценю ваш опыт в этом вопросе.

1 Ответ

5 голосов
/ 02 октября 2012

Вы довольно внимательны с процессом передачи обслуживания в CLR, но здесь все становится интереснее:

  • Если каждый шаг запроса привязан к ЦП / в противном случае является синхронным, то да: этот запрос будет поглощать этот поток в течение его времени жизни.

  • Однако, если какая-либо часть задач обработки запросов выполняет какие-либо асинхронные или даже какие-либо операции ввода-вывода, относящиеся за пределами чисто управляемого кода (соединение БД, чтение / запись файла и т. Д.), Это возможно, если нет вероятно, что это произойдет:

    • Запрос поступает в CLR-землю, подобранную по нитям A

    • Запрос вызовов к файловой системе

    • Под капотом переход к неуправляемому коду происходит на некотором уровне, что приводит к тому, что поток порта завершения ввода-вывода ( отличается от потока обычных пулов потоков) распределяется аналогично обратному вызову .

    • Как только происходит такая передача, поток A возвращает обратно в пул потоков, где он может обслуживать запросы.

    • Как только задача ввода-вывода завершается, выполнение ставится в очередь, и предположим, что поток A занят - поток B принимает запрос.

Такое «забавное» поведение также называется «Ловкость потоков» и является одной из причин, чтобы по возможности избегать использования НИЧЕГО, то есть статического потока, в приложении ASP.NET.

Теперь к некоторым вашим вопросам:

  • Предел очереди запросов - это количество запросов, которые могут быть "в очереди", прежде чем запросы начнут отбрасываться. Если бы у вас было, скажем, исключительно «пакетное» приложение, в котором вы можете получить МНОЖЕСТВО очень короткоживущих запросов, установка этого высокого значения предотвратит отбрасывание запросов, поскольку они будут собираться в очереди, но расходуются одинаково быстро.

  • Асинхронные обработчики позволяют вам создать такой же тип поведения «позвони мне, когда закончишь», как в приведенном выше сценарии; например, если вы говорите, что необходимо выполнить вызов веб-службы, синхронный вызов через, скажем, некоторый вызов HttpWebRequest по умолчанию будет блокировать до завершения, блокируя этот поток до тех пор, пока это не будет сделано. Вызов одной и той же службы асинхронно (или асинхронный обработчик, любой шаблон Begin / EndXXX ...) дает вам некоторый контроль над тем, кто на самом деле связан, - ваш вызывающий поток может продолжать выполнение действий до тех пор, пока этот веб-сервис не вернется, что на самом деле может быть после запрос выполнен.

  • Следует отметить, что есть только один ThreadPool - все потоки, не относящиеся к IO, извлекаются оттуда, поэтому, если вы переместите все на асинхронную обработку, вы можете просто укусить себя, исчерпав пул потоков, выполняя фоновую работу, и не обслуживает запросы.

...