Маршрутизация запросов приложений 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.