IIS7 Application Request Routing (обратный прокси-сервер arr) в сочетании с управляемым модулем - время ожидания - PullRequest
12 голосов
/ 29 марта 2011

Я пытаюсь создать прокси, который будет обслуживать запросы к внутреннему сайту (скрывая источник), но в то же время проверять пакеты и асинхронно обрабатывать их.

например. скажем, все вызовы SOAP к http://www.foo.com перейдут к http://192.168.1.1, и одновременно будут сохранены в БД для последующего анализа. Внутренний сервер - это черный ящик, поэтому изменение чего-либо на нем выходит за рамки этого вопроса.

Во всяком случае, я настроил ARR, с обратным прокси, сделал фильтр перезаписи URL с подстановочными знаками, все работает безупречно. Затем я попытался добавить управляемый модуль HttpModule, написанный на C #, и подключился к Application_BeginRequest и Application_EndRequest. Я могу получить доступ к заголовкам запросов, заголовкам ответов на конечный запрос (пул приложений находится в интегрированном режиме) и даже могу читать содержимое ответа из выходного потока, установив фильтр в Response.Filter, который кэширует все записи в дополнительном потоке памяти.

Проблема в том, что в тот момент, когда я пытаюсь прочитать (внутри обработчика модуля BeginRequest) входной поток из запроса, ARR остается некоторое время и выдает

Ошибка HTTP 502.3 - Bad Gateway The Тайм-аут операции ApplicationRequestRoutingHandler Код ошибки 0x80072ee2

Так что время истекло.

Просмотр с отслеживанием невыполненных запросов Я вижу:

MODULE_SET_RESPONSE_ERROR_STATUS Предупреждение ModuleName = "ApplicationRequestRouting", Уведомление = "EXECUTE_REQUEST_HANDLER", HttpStatus = "502", HttpReason = "Плохо Шлюз ", 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 модуль

Идеи? Спасибо / Космин

Ответы [ 3 ]

7 голосов
/ 18 марта 2012

Если вы можете переключиться на .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 .

4 голосов
/ 10 февраля 2012

Я знаю, что это годичный вопрос, но я прошел через то же самое и нашел решение. Итак, я выкладываю это здесь для всех, кто сталкивается с этим.

В моем случае я видел только проблему тайм-аута с POST запросами.

Похоже, что 2.0 / 2.1 ARR предполагает , что входной поток будет в начале опубликованных данных. Однако следующий код (например) нарушит это предположение:

    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. Если вы прочитаете это напрямую, он не будет работать.

2 голосов
/ 23 февраля 2012

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

Мой основной сервер основан на MVC, и он просматривает значения Request.Form в методе Application_BeginRequest. При обращении к значениям формы ARR не может переслать тело HTTP-запроса POST. GET-запросы будут работать нормально, так как тела нет.

У меня есть routes.IgnoreRoute ("Forum/{*pathInfo}"); в качестве зарегистрированного маршрута, но ARR работает как HttpModule и не включается до тех пор, пока не появится в конвейере. Это означает, что моему приложению, основанному на MVC, предоставляется возможность доступа к содержимому тела POST, что каким-то образом препятствует ARR получать доступ к самому телу и пересылать его на прокси-сервер.

Вот сообщение, связанное с Космином на форумах iis.net: ARR 2.0 BUG - в сочетании с тайм-аутом управляемого модуля http при чтении входных данных

В моем приложении у меня есть все myserver.com / Forum / * запросы на обратный прокси-сервер для отдельного приложения на другом сервере. Поэтому я просто проверил HttpContext.Current.Request.Url в методе Application_BeginRequest моего приложения MVC, чтобы убедиться, что он не содержит / Forum перед доступом к значениям Request.Form. Как только я сделал это, POST тела сделали это через ARR просто отлично.

ОБНОВЛЕНИЕ: после дальнейшего тестирования кажется, что все еще есть проблемы с ARR, поскольку POST от неаутентифицированных пользователей все еще терпит неудачу. Вместо основного веб-сайта MVC я создал фиктивный веб-сайт IIS .NET 4.0 с одним документом Default.html. Но я все еще сталкивался с проблемами с запросами POST и ARR. Затем я переключаю пул приложений на ASP.NET 2.0 и, как вы знаете, он работает. На данный момент я должен предположить, что что-то в конвейере .NET 4.0 обращается к входному потоку, что препятствует доступу ARR к самому входному потоку для пересылки тела POST.

...