Маршрутизация запросов приложений IIS7 (обратный прокси-сервер) в сочетании с управляемым модулем — тайм-аут

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

Например. скажем, все вызовы 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 Время ожидания операции истекло Код ошибки обработчика ApplicationRequestRoutingHandler 0x80072ee2

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

Глядя на отслеживание неудачных запросов, я вижу:

MODULE_SET_RESPONSE_ERROR_STATUS Предупреждение ModuleName="ApplicationRequestRouting", Notification="EXECUTE_REQUEST_HANDLER", HttpStatus="502", HttpReason="Bad Gateway", HttpSubStatus="3", ErrorCode="2147954402", ConfigExceptionInfo="" SET_RESPONSE_ERROR_DESCRIPTION Warning ErrorDescription="Операция время вышло"

Теперь любые подобные сообщения в сети не помогли, так как это не ошибка тайм-аута (прокси имеет настройку 120 секунд, ответы страницы менее 100 мс), а момент, когда я комментирую код обработчика, который пытается прочитать данные формы или данные InputStream, все работает как шарм.

Даже если я установлю позицию входного потока на 0 после его чтения, я все равно получаю тайм-ауты. Если я прочитаю входной поток в EndRequest, он получит 0 байтов, даже если это был запрос POST. (что явно неправильно)

Есть ли у ARR ошибка в том, что я пытаюсь прочитать входной поток до того, как он попытается перенаправить его?

Что использовалось: Windows Server 2008 R2 IIS 7.5 ARR v2 .Net Framework 3.5 модуль

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


person user682385    schedule 29.03.2011    source источник


Ответы (4)


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

person Andrés Robinet    schedule 17.03.2012

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

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

person Devon_C_Miller    schedule 09.02.2012

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

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

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

Вот соответствующее сообщение Космина на форумах iis.net: Тайм-аут модуля 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.

person Todd Smith    schedule 22.02.2012

按照正常来说,再iis网站界面会有一个запрос приложения

кэш маршрутизации 的 icon, 可以点击 设置timeout 但是这里没有显示

找到了 官方说明可以用命令行解决这个问题

https://blogs.iis.net/richma/502-3-bad-gateway-the-operation-timed-out-with-iis-application-request-routing-arr ​ blogs.iis. сеть

执行以下命令,然后重启下网站服务

进入到C:\Windows\System32\inetsrv

appcmd.exe set config -section:system.webServer/proxy/timeout:00:00:45/commit:apphost

https://zhuanlan.zhihu.com/p/157557980

person andot    schedule 08.07.2020