2011-04-11 67 views
1

我對Web服務世界中的一些東西非常困惑,我希望有人能向我解釋它。WCF,SOAP,Plain Old XML

這是我想要的:我想HTTPPost一個XML文檔到https://www.whatever.com/myservice(。???)。在那個服務中,我想獲得這個XML文檔,做一些東西,然後回覆一個非常簡單的XML文檔 - 比如「<xml....><success>TRUE</success>

我不能做SOAP或JSON或其他任何東西。我必須遵守現有的規定。有數百家不同的公司以我描述的格式向我們發送數據,並且添加要求將其全部封裝在SOAP中是不可能的。

當使用WCF Web服務,它看來求我有這樣發送:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetData xmlns="http://tempuri.org/"><value>3</value></GetData></s:Body></s:Envelope> 

當使用的.asmx頁,響應總是發送與一個XML文檔命名空間(http:// tempuri,或者如果我改變了它,然後改變它)。這是不必要的,可能會破壞所有現有的代碼。

當使用通用處理程序(.ashx)時,我可以確切地控制返回的內容,但我被告知遠離.ashx頁面,因爲它們攜帶完整的ASP.Net會話類型代碼,並且它速度要慢得多。

我會用什麼來解決這個問題,讓我的代碼儘可能快?

編輯:如果有人關心,每小時10,000個請求的問題是我們在這一年的高峯流量。我們平均每天處理50-60個傳入請求,但在12月期間,它每小時可以處理10,000個請求。我們希望增長,但要做到這一點,我會在Rackspace中添加一個負載均衡器和一些更多的機器。

我們目前的服務提供商在這段時間內不堪重負,因此我們錯過了很多錢。因此,我的代理將在前端執行我們最基本的檢查之一(每小時更新一次數據庫的重複檢查),並將清除我們必須發送給我們當前提供商的75%的流量。目前的供應商爲我們提供這些線索的承保,我不會取而代之,只是增加一個看門人來減輕他們服務器上的壓力。

感謝您的幫助。我最近在StackOverflow上詢問了一系列Web服務問題,試圖解決我將面臨的許多問題。

+0

我相信處理程序(.ashx)只使用會話狀態,如果他們實現'IRequiresSessionState'。 – 2011-04-11 19:00:45

+0

它是.ashx。也許我誤解了我被告知的事情,但我不這麼認爲。感謝您的評論。 – 2011-04-11 19:35:21

回答

2

你在說什麼是POX服務 - 也稱爲普通舊XML。

誰告訴你IHttpHandlers攜帶會話代碼是錯誤的 - 他們不會除非你explicitly enable session state。現在,它確實有ASP.NET管道開銷,但除非你使用一些瘋狂的輕量級web套接字服務器,否則這並不重要,因爲任何形式的IIS託管服務都會有類似的開銷。而且,如果這是一個面向公衆的互聯網服務,IIS會爲您提供一些您可能想要的精巧內容。諸如SSL,請求記錄以及與其他東西操作集成的東西正在用於觀察事物。

至於如何到達那裏,因爲你已經定義了一個格式,ASMX和WCF的默認(SOAP)行爲根據定義而定。爲了靈活性,服務的實際邏輯應該分開實現,留下負責接受請求的外部位,從XML轉換並將響應作爲正確格式化的XML發回。

這讓你有幾個選擇:

  • 也許最簡單的,尤其是如果這是螺栓到現有的.NET網站,將是一個自定義的IHttpHandler。與其他地方相比,你將不得不在其他地方低一點,但如果這確實會帶入一組XML並將響應吐出,那麼這項工作並非無法克服。一個很大的優點是對輸出端的控制是有限的,所以如果你有一個長時間運行的任務,你可以很容易地傳送響應。

  • ASP.NET MVC web服務可能會比IHttpHandler更簡單,因爲您不必非常深入地瞭解POST變量,而且如果您正在使用MVC站點,這也是有意義的。

  • 如果XML以不介意的方式進行格式化,那麼帶有webhttp綁定的WCF可以工作。但是你會有一些笨蛋笨蛋,因爲根據我的經驗,WCF從來不想完全適合你喜歡在電線上看到的某種XML。

  • 其他的東西,如OpenRasta,可以在這裏很好地工作。它真正的意思,這些各種各樣的POX風格的場景,將很容易讓你使用你的XML格式等

只要速度,真正的問題回答不是「這是可能是最快的「而是」這足夠快了嗎?「特別是考慮到HTTP和遠程通信的性質,在大多數情況下,您可能能夠創建的任何服務器端效率都無關緊要,因爲請求通過線路需要的時間比它長數百倍得到處理。如果你確實有一個相對乾淨的服務邏輯實現,那麼你將能夠切換通信堆棧,直到找到最適合你的通信堆棧。

+0

這將是一個項目中唯一的東西。沒有其他aspx頁面,什麼都沒有。實際上,我正在接收和XML文件,做它的東西,發送給第三方,等待他們的迴應,然後發送回原始提供商。我需要能夠處理每小時10,000個請求。 – 2011-04-11 19:22:33

+0

那麼,我會問的問題是當前的解決方案處理。行政人員的甜蜜夢想似乎是10k /小時的數字。沒關係,它不在你的掌控之中 - 瓶頸在於第三方服務。我真的會看消息隊列,因爲這裏的挑戰是如何處理來自第三方的發送/接收,而不會阻止事情或以其他方式調用問題。 – 2011-04-11 19:34:04

1

這很少取決於你有什麼樣的應用程序?如果是ASP.net WebForms,則可能只有標準Page,帶有Page_Load方法,您可以在其中處理請求,並將其放入HttpCurrent.HttpContex.Response對象中。

如果是MVC,則應該使用自定義的ActionResult進行操作。

但是至於我,我沒有看到Generic Handlers .ashx有什麼問題。我會和它一起去的。

1

作爲通用處理程序的Ashx直到您specify it纔會話。您所描述的有時稱爲XML服務。 WCF默認允許SOAP和REST服務。我不確定您是否可以使用每個資源(消息類型)的唯一URL,這將允許您使用REST服務。這意味着你的URL看起來像https://www.whatever.com/myservice/something其中一些將被用於映射到操作標記WebInvoke屬性爲:

[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    [WebInvoke(Method = "POST", UriTemplate="Something", 
       BodyStyle = WebMessageBodyStyle.Bare, 
       RequestFormat = WebMessageFormat.Xml, 
       ResponseFormat = WebMessageFormat.Xml)] 
    CompositeTypeMessage GetData(CompositeTypeMessage composite); 
} 

您也可以使用本機WCF不休息來定義XML服務,但它需要很多的努力:

首先,您必須定義自定義綁定,其中重要部分是messageVersion=None

<bindings> 
    <customBinding> 
    <binding name="XmlService"> 
     <textMessageEncoding messageVersion="None"/> 
     <httpTransport/> 
    </binding> 
    </customBinding> 
</bindings> 
<services> 
    <service name="XmlService.Service"> 
    <endpoint address="" binding="customBinding" bindingConfiguration="XmlService" contract="XmlService.IService"/> 
    <host> 
     <baseAddresses> 
     <add baseAddress="http://localhost:8732/XmlService"/> 
     </baseAddresses> 
    </host> 
    </service> 
</services> 

然後,你必須定義合同,並刪除默認的命名空間:

[ServiceContract(Namespace = "")] 
public interface IService 
{ 
    [OperationContract] 
    CompositeTypeMessage GetData(CompositeTypeMessage composite); 
} 

// Now here you can make main decission. Do you want wrapper for data 
// or not. If you don't use message contract and use data contract directly 
// each request will be wrapped in the element with the same name as operation 
// and response will be wrapped in the element with the name of operation + 
// Response suffix. Message contract allows you defining custom wrapper name 
// or turning it off. 
[MessageContract (WrapperNamespace = "", IsWrapped = false)] 
public class CompositeTypeMessage 
{ 
    [MessageBodyMember(Namespace = "")] 
    public CompositeType Data { get; set; } 
} 

[DataContract(Namespace = "")] 
public class CompositeType 
{ 
    bool boolValue = true; 
    string stringValue = "Hello "; 

    [DataMember] 
    public bool BoolValue 
    { 
     get { return boolValue; } 
     set { boolValue = value; } 
    } 

    [DataMember] 
    public string StringValue 
    { 
     get { return stringValue; } 
     set { stringValue = value; } 
    } 
} 

最後一點是實現自定義IDispatchOperationSelector行爲。刪除所有與SOAP相關的功能可以打破當前WCF選擇正確操作來處理消息的能力。你必須定義一個新的例子,例如根據根請求元素通過一些約定來選擇操作。 Here是MSDN示例如何構建和使用類似的行爲。