IIS7应用程序请求路由(arr反向代理)与托管模块相结合 - 超时

时间:2011-03-29 16:11:36

标签: iis-7 timeout httpmodule reverse-proxy

我正在尝试构建一个代理,为内部站点提供请求(隐藏原点),但同时检查数据包并异步后处理它们。

E.g。假设所有对http://www.foo.com的SOAP调用都将转到http://192.168.1.1,同时存储在数据库中进行后期分析。内部服务器是一个黑盒子,所以更改它的内容超出了这个问题的范围。

无论如何,我已经配置了ARR,使用反向代理,使用通配符进行URL重写过滤,所有工作都完美无瑕。然后,我尝试添加一个用C#编写的托管HttpModule,并挂钩到Application_BeginRequest和Application_EndRequest。我能够在最终请求(应用程序池处于集成模式)中访问请求标头,响应标头,甚至能够通过在Response.Filter上设置过滤器来读取输出流中的响应内容,该过滤器将所有写入缓存在附加内存流中。

问题是,当我尝试读取(在模块BeginRequest处理程序内)来自请求的输入流时,ARR会停留一段时间并抛出一个

  

HTTP错误502.3 - 糟糕的网关   操作超时处理程序   ApplicationRequestRoutingHandler   错误代码0x80072ee2

所以它超时了。

查看失败的请求跟踪我看到:

  

MODULE_SET_RESPONSE_ERROR_STATUS   警告   模块名= “ApplicationRequestRouting”,   通知= “EXECUTE_REQUEST_HANDLER”,   HttpStatus =“502”,HttpReason =“不好   Gateway“,HttpSubStatus =”3“,   错误码= “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   模块

想法? 谢谢 /科斯明

4 个答案:

答案 0 :(得分:6)

如果您可以切换到.Net Framework 4,那么就有一个解决方案。

在HttpModule事件处理程序中完成BeginRequest / EndRequest后,添加对 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

答案 1 :(得分:4)

我知道这是一个一年前的问题,但我只是经历了同样的事情并找到了解决方案。所以,我在这里发布它是为了遇到这个问题的其他人。

就我而言,我只看到了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 :(得分:2)

我刚遇到这个错误,你的经历帮助我确定了根本原因。

我的主服务器是基于MVC的,它查看Application_BeginRequest方法中的Request.Form值。如果访问表单值,则ARR无法转发HTTP POST请求的正文。由于没有正文,GET请求将正常工作。

我有routes.IgnoreRoute ("Forum/{*pathInfo}");作为注册路线,但ARR作为HttpModule运行,并且直到管道中的后期才开始运行。这意味着我的基于MVC的应用程序有机会访问POST主体的内容,以某种方式阻止ARR访问主体本身并将其转发到代理服务器。

这是Cosmin在iis.net论坛上的相关帖子:ARR 2.0 BUG - combined with managed http module timeout on read inputstream

在我的应用程序中,我将所有 myserver.com/Forum / * 请求反向代理到另一台服务器上的单独应用程序。所以我只是检查了我的MVC应用程序的 Application_BeginRequest 方法中的HttpContext.Current.Request.Url,以确保它在访问Request.Form值之前不包含/ Forum。一旦我这样做,POST机构通过ARR就可以了。

更新:在进一步测试后,似乎ARR仍然存在问题,因为来自未经身份验证的用户的POST仍然失败。而不是主网站是MVC我创建了一个虚拟的IIS .NET 4.0网站,其中包含一个Default.html文档。但我仍遇到POST请求和ARR的问题。然后我将应用程序池切换到ASP.NET 2.0,你知道什么,它的工作原理。在这一点上,我必须假设.NET 4.0管道中的某些东西正在访问输入流,这阻止了ARR访问输入流本身以转发POST主体。

答案 3 :(得分:0)

按照正常来说,再iis网站界面会有一个应用程序请求

routing cache的图标,可以单击设置超时,但是这里没有显示

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

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

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

进入到C:\ Windows \ System32 \ inetsrv:管理员命令行工具执行以下命令

appcmd.exe设置配置-section:system.webServer / proxy / timeout:“ 00:00:45” / commit:apphost

重启下网站服务 我写的财经报地址 https://zhuanlan.zhihu.com/p/157557980