2011-08-23 58 views
2

問題: DataServiceContext.SaveChanges()以「302 - 移動」響應失敗。WCF數據服務錯誤 - 302在與HTTPS + Load Balancer相關的SaveChanges()上移動?

背景/可疑原因:負載平衡器! - 我們最近更改了基礎設施,以便我們的Web服務器現在位於負載均衡器的後面,該負載均衡器也處理ssl。客戶將服務定位爲HTTPS,但由於SSL是由負載均衡器完成的(我相信大多數人都熟悉這種類型的設置),IIS最終會處理HTTP請求。無論如何,我們最終得到的是包含使用HTTP而不是HTTPS的URI的提要。 (請參閱http請求中的GET請求/響應,而不是httpS)。該行爲是非常奇怪的,因爲當我打電話調用SaveChanges()發送一個MERGE(如預期),我拿回302:

HTTP/1.1 302 Object moved 
Location: https://some.domain.org/CMSProfileService/ProfileDataService.svc/Mails(guid'80fef993-a4b5-4343-a908-28c2c6517a81') 
Connection: close 

但WCF一直在嘗試MERGE,並使用HTTP(約50時間),然後最後拋出一個異常與消息,「」處理此請求時發生錯誤。「,內部excepion消息是」找到「。:)

當我直接指向服務器(繞過loadbalancer和ssl )一切工作正常。當SSL直接在IIS中註冊時,一切都可以正常工作。

必須有一些配置設置/屬性,我是沒有找到。 Viteks answer到一個類似的問題嚇了我一下。

這是從提琴手

GET https://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails()?$filter=Status%20eq%20'Queued'&$orderby=Timestamp&$expand=Attachments HTTP/1.1 
User-Agent: Microsoft ADO.NET Data Services 
DataServiceVersion: 1.0;NetFx 
MaxDataServiceVersion: 2.0;NetFx 
UserName: 
Accept: application/atom+xml,application/xml 
Accept-Charset: UTF-8 
Host: some.domain.org 
Connection: Keep-Alive 

和這裏的原始GET請求的原始響應(修整):

HTTP/1.1 200 OK 
Set-Cookie: ARPT=RPZVOOS192.168.94.118CKOUM; path=/ 
Cache-Control: no-cache 
Content-Length: 45849 
Content-Type: application/atom+xml;charset=utf-8 
Server: Microsoft-IIS/7.5 
DataServiceVersion: 1.0; 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 
Date: Mon, 22 Aug 2011 14:56:46 GMT 

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<feed xml:base="http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> 
    <title type="text">Mails</title> 
    <id>http://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails</id> 
    <updated>2011-08-22T14:56:47Z</updated> 
    <link rel="self" title="Mails" href="Mails" /> 
    <entry> 
    <id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')</id> 
    <title type="text"></title> 
    <updated>2011-08-22T14:56:47Z</updated> 
    <author> 
     <name /> 
    </author> 
    <link rel="edit" title="Mail" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')" /> 
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments" type="application/atom+xml;type=feed" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments"> 
     <m:inline> 
     <feed> 
      <title type="text">Attachments</title> 
      <id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments</id> 
      <updated>2011-08-22T14:56:47Z</updated> 
      <author> 
      <name /> 
      </author> 
      <link rel="self" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments" /> 
     </feed> 
     </m:inline> 
    </link> 
    <category term="XXX.YYY.Profile.Repository.Mail" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
    <content type="application/xml"> 
     <m:properties> 
     <d:MailId m:type="Edm.Guid">c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd</d:MailId> 
     <d:Timestamp m:type="Edm.DateTime">2011-07-28T12:51:37.69</d:Timestamp> 
     <d:ApplicationCode>EREF</d:ApplicationCode> 
     <d:Status>Queued</d:Status 
. 
. 
. 
+0

Vitek,你在哪裏人! ;) – Dan

+0

你正在使用什麼樣的負載均衡器?負載均衡器中有任何配置嗎? –

+0

它是一個較老的cisco(〜5歲)負載均衡器,不確定型號的確切數據,我將在此處檢查併發布信息 – Dan

回答

0

終於解決了這個討厭的問題。其實有兩個問題。

問題#1:在負載均衡器中使用https託管在IIS中的WCF數據服務使用http URI而不是https創建提要。這是可以理解的,是我對這個問題的第一次猜測。通過大量的挖掘,我遇到了this文章,它提供了一個非常簡單的解決方案。

在我服務的構造函數我掛接到處理請求事件

ProcessingPipeline.ProcessingRequest += ProcessingPipeline_ProcessingRequest; 

在事件處理程序,我用提到的文章,並取得了一定的調整,基本上採取的主機,方案和端口從clientExpectsUri並將它們應用於請求Uri。我也只是尋找一個自定義標題,我稱之爲「X-Client-Expects-RootUri」,防火牆外的客戶端需要發送,如果他們想要有效的提要。

static void ProcessingPipeline_ProcessingRequest(object sender, DataServiceProcessingPipelineEventArgs e) 
{ 
    if (e.OperationContext.RequestHeaders.AllKeys.Contains(ClientExpectsUriKey)) 
     ProcessUri(new Uri(e.OperationContext.RequestHeaders[ClientExpectsUriKey]));  
} 

private static void ProcessUri(Uri clientExpectsRootUri) 
{ 
    if (clientExpectsRootUri != null) 
    { 
     var requestUri = OperationContext.Current.IncomingMessageProperties.ContainsKey("MicrosoftDataServicesRequestUri") 
           ? OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] as Uri : HttpContext.Current.Request.Url; 

     var serviceUri = clientExpectsRootUri; 

     var serviceUriBuilder = new UriBuilder(serviceUri); 

     var requestUriBuilder = new UriBuilder(requestUri) 
            { 
             Host = serviceUriBuilder.Host, 
             Scheme = serviceUriBuilder.Scheme, 
             Port = serviceUriBuilder.Port 
            }; 

     if (!serviceUriBuilder.Path.EndsWith("/")) //the base uri should end with a slash... 
      serviceUriBuilder.Path = serviceUriBuilder.Path += "/"; 

     OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = serviceUriBuilder.Uri; 
     OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = requestUriBuilder.Uri; 
    } 
} 

我真的喜歡上了這設計的一些反饋意見,因爲我基本上是要求客戶告訴我如何通過自定義標題返回URI。我將在未來考慮修改負載平衡器以自動添加這些標頭。

問題#2:沒有爲MERGE和其他非RFC http方法配置負載平衡器。此問題的解決方案非常簡單,只需在DataServiceContext上將usePostTunneling設置爲true即可。如果任何人有腳本來爲思科11503啓用非RFC的http方法,我很樂意擁有它們。 ;-)

2

這裏的問題是可能的self/links編輯鏈接是HTTP,而不是HTTPS,因此客戶端無法使用鏈接訪問數據。每Vitek的scary answer

不幸的是服務器不知道它在哪裏。

我能想到幾個選項(他們都沒有特別好的)的:

  1. 使用,它告訴數據服務它的根是HTTPS定製IDataServiceHost2:// ...通過AbsoluteServiceUri財產。這樣數據服務應該產生適當的URLS
  2. 實現一個WCF行爲,刪除http:// url並用https://替換它們,這將涉及很多緩衝等。檢出這個JSONP example哪些修改了來自服務器的響應。

-Alex

+0

是的,這是我的想法。有沒有HTTP標頭,我可以配置負載均衡器發送WCF可以評估並確定他在代理後面運行?無論如何,我會嘗試實施IDataServiceHost2並回來。 – Dan

+0

如果您使用在IIS中託管時使用的標準DataServiceHost,我不認爲您可以執行任何操作。 –

+0

好的,我有一個更新,我在這裏發現了另一篇文章http://blogs.msdn.com/b/peter_qian/archive/2010/03/24/overwriting-the-service-root-uri-in-wcf-data -service.aspx看起來很有前途,現在我的feed看起來很完美(到處都是https uris),但是我得到了完全相同的行爲(302響應)。看起來這應該現在工作,但它不是,所以明天我想我會實現IDataServiceHost2,但我有一種感覺,我最終會遇到同樣的問題。 – Dan