2011-03-29 35 views
10

我想構建一個代理服務器向內部站點發送請求(隱藏起源),但同時檢查數據包並異步發佈 - 處理它們。IIS7應用程序請求路由(ARR反向代理)與託管模塊結合 - 超時

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 = 「壞 網關」, 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的 模塊

想法? 謝謝 /Cosmin

回答

3

我知道這是一個古老的問題,但我只是通過相同的事情,並找到了解決方案。所以,我在這裏發佈給其他任何碰到此問題的人。

就我而言,我只看到了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

我剛碰到這個bug,你的經歷幫助我確定了根本原因。

我的主服務器是基於MVC的,它查看Application_BeginRequest方法中的Request.Form值。如果訪問表單值,則ARR無法轉發HTTP POST請求的主體。由於沒有正文,GET請求將正常工作。

我有routes.IgnoreRoute ("Forum/{*pathInfo}");作爲註冊路由,但ARR作爲一個HttpModule運行,並且直到稍後在管道中才會啓動。這意味着我的基於MVC的應用程序有機會訪問POST主體的內容,從而以某種方式防止ARR訪問主體本身並將其轉發到代理服務器。

這裏是科斯明的上iis.net論壇相關帖子:ARR 2.0 BUG - combined with managed http module timeout on read inputstream

在我的應用程序都myserver.com/Forum/*請求是反向proxy'd到另一臺服務器上的一個單獨的應用程序。所以我只是在我的MVC應用程序的Application_BeginRequest方法中檢查了HttpContext.Current.Request.Url,以確保它在訪問Request.Form值之前不包含/ Forum。一旦我做到了,POST機構通過ARR就可以了。

UPDATE:經過進一步測試,似乎仍然存在ARR問題,因爲來自未認證用戶的POST仍然失敗。而不是主要的網站是MVC我創建了一個虛擬的IIS .NET 4.0網站與一個Default.html文檔。但是我仍然遇到POST請求和ARR的問題。然後,我將應用程序池切換到ASP.NET 2.0,您知道什麼,它的工作原理。此時,我必須假設.NET 4.0管道中的某些內容正在訪問阻止ARR訪問輸入流本身以便轉發POST主體的輸入流。

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

+0

我在.NET 4.0上,這對我來說伎倆! Thanx robinet – 2012-08-09 13:12:39

相關問題