Маршрутизация запросов приложений IIS7 (обход обратного прокси) в сочетании с управляемым модулем - тайм-аут
Я пытаюсь создать прокси-сервер, который будет обслуживать запросы на внутренний сайт (скрывая исходный код), но в то же время проверять пакеты и асинхронно обрабатывать их.
например. пусть все вызовы SOAP на http://www.foo.com перейдут на http://192.168.1.1 и в то же время сохраняться в БД для пост-анализа. Внутренний сервер является черным ящиком, поэтому изменение чего-то на нем выходит за рамки этого вопроса.
Во всяком случае, я настроил ARR с обратным прокси-сервером, переработал фильтр URL с помощью подстановочных знаков, все работает безупречно. Затем я попытался добавить управляемый HttpModule, написанный на С#, и подключиться к Application_BeginRequest и Application_EndRequest. Я могу получить доступ к заголовкам запросов, заголовкам ответов в конце запроса (пул приложений находится в интегрированном режиме) и даже способен считывать содержимое ответа из выходного потока, устанавливая фильтр в Response.Filter, который кэширует все записи в дополнительном потоке памяти.
Проблема в том, что в тот момент, когда я пытаюсь прочитать (внутри обработчика BeginRequest модуля) входной поток из запроса, ARR остается некоторое время и бросает
Ошибка HTTP 502.3 - Bad Gateway время ожидания операции ApplicationRequestRoutingHandler Код ошибки 0x80072ee2
Итак, это время.
Глядя на отслеживание неудачных запросов, я вижу:
MODULE_SET_RESPONSE_ERROR_STATUS Предупреждение ModuleName = "ApplicationRequestRouting", Уведомление = "EXECUTE_REQUEST_HANDLER", HttpStatus = "502", HttpReason = "Плохо Gateway", HttpSubStatus = "3", ErrorCode = "2147954402", ConfigExceptionInfo = "SET_RESPONSE_ERROR_DESCRIPTION Предупреждение ErrorDescription =" Время выполнения операции из "
Теперь любые похожие сообщения в сети не помогли, так как это не ошибка таймаута (прокси имеет 120-секундную настройку, ответы на страницы менее 100 мс), и в тот момент, когда я комментирую код обработчика, который пытается прочитайте данные FORM или данные InputStream, все работает как прелесть.
Даже если я установил позицию входного потока на 0 после прочтения, я все равно получаю таймауты.
Если я прочитаю входной поток на EndRequest, он получит 0 байтов, даже если это был запрос POST. (что явно неправильно)
Есть ли у ARR ошибка в том, что я пытаюсь прочитать входной поток, прежде чем пытаться перенаправить его?
Используемые вещи: Windows Server 2008 R2 IIS 7.5 ARR v2.Net Framework 3.5 модуль
Идеи?
благодаря
/Космин
Ответы
Ответ 1
Если вы можете переключиться на .Net Framework 4, для этого есть решение.
После того, как вы закончите свой BeginRequest/EndRequest в обработчике событий HttpModule, добавьте вызов HttpRequest.InsertEntityBody.
/* BeginRequest event: Executes before request is processed */
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpRequest request = application.Context.Request;
// Do something with request
DoMyOwnRequestProcessing(request);
// After you finish, make sure IIS gets the entity body
// For example, Application Request Routing needs this
request.InsertEntityBody();
}
Взгляните на это на MSDN: HttpRequest.InsertEntityBody.
Ответ 2
Я знаю, что это вопрос на год, но я просто прошел одно и то же и нашел решение. Итак, я размещаю его здесь для всех, кто сталкивается с этим.
В моем случае я только видел проблему с тайм-аутом с запросами POST
.
Похоже, что ARR 2.0/2.1 предполагает, что входной поток будет в начале опубликованных данных. Однако следующий код (например) нарушит это предположение:
HttpContext context = HttpContext.Current;
HttpRequest request = context.Request;
string value = request.Params["Name"];
Ключ описывает описание Params
Gets a combined collection of System.Web.HttpRequest.QueryString,
System.Web.HttpRequest.Form, System.Web.HttpRequest.ServerVariables,
and System.Web.HttpRequest.Cookies items."`
Когда запрос является POST, доступ к Params
будет считывать опубликованные данные из входного потока, что делает недействительным предположение ARR. Как будет видно из входного потока.
Я знал, что данные, которые мне нужны, были в строке запроса, а не в опубликованных данных, поэтому я работал над этим, обратившись к QueryString
вместо Params
. Это позволяет избежать чтения опубликованных данных и отлично подходит для меня.
string value = request.QueryString["Name"];
Эта проблема, как представляется, исправлена в ARR 2.5.
Обновление ARR представляется единственным решением, если вам нужно получить доступ к опубликованным данным перед передачей в ARR. Ключ должен позволить HttpRequest обрабатывать данные в Params
. Если вы прочитаете его напрямую, это не сработает.
Ответ 3
Я просто столкнулся с этой ошибкой, и ваши впечатления помогли мне определить основную причину.
Мой главный сервер основан на MVC, и он смотрит на значения Request.Form в методе Application_BeginRequest
. Если доступны значения формы, ARR не передает текст запроса HTTP POST. Запросы GET будут работать нормально, поскольку нет тела.
У меня есть routes.IgnoreRoute ("Forum/{*pathInfo}");
как зарегистрированный маршрут, но ARR работает как HttpModule и не запускается до конца в конвейере. Это означает, что моему приложению на базе MVC предоставляется возможность доступа к содержимому тела POST, которое каким-то образом предотвращает доступ ARR к самому телу и пересылку его на сервер proxy'd.
Вот сообщение Cosmin на форумах iis.net: ARR 2.0 BUG - в сочетании с таймаутом управляемого http-модуля при чтении входного потока
В моем приложении у меня есть все myserver.com/Forum/* запросы, обратные прокси, в отдельное приложение на другом сервере. Поэтому я просто проверил HttpContext.Current.Request.Url в моем приложении MVC Application_BeginRequest, чтобы убедиться, что он не содержит/Форум перед доступом к значениям Request.Form. Как только я это сделал, тела POST сделали это через ARR просто отлично.
ОБНОВЛЕНИЕ: после дальнейшего тестирования, похоже, что все еще есть проблемы с ARR, поскольку POST от неидентифицированных пользователей все еще не работает. Вместо основного веб-сайта MVC я создал фиктивный веб-сайт IIS.NET 4.0 с единственным документом Default.html. Но у меня все еще возникали проблемы с запросами POST и ARR. Затем я переключу пул приложений на ASP.NET 2.0, и что вы знаете, он работает. На этом этапе я должен предположить, что что-то в конвейере .NET 4.0 обращается к входному потоку, который препятствует доступу ARR к самому входному потоку, чтобы перенаправить тело POST.