早先我們觀察過WCF HTTP vs TCP的傳輸量差異,該測試呼叫GetData()作業傳入數字接回字串,並不算真的用到WCF的DataContract/DataMember序列化功能,故這次改聚焦在物件資料的序列化上,再做一次比較。
我小幅改寫Visual Studio WCF專案範本的CompositeType,增加一個IntValue。
[DataContract]
publicclass CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
int intValue = 1;
[DataMember]
publicbool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
publicstring StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
[DataMember]
publicint IntValue
{
get { return intValue; }
set { intValue = value; }
}
}
GetDataUsingDataContract()也做一點改寫,傳回值改成CompositeType[],傳回資料筆數由傳入的CompositeType.IntValue決定,藉此彈性控制傳回結果筆數,以觀察資料筆數多寡對資料量的影響。
public CompositeType[] GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
thrownew ArgumentNullException("composite");
}
var res = new List<CompositeType>();
for (var i = 0; i < composite.IntValue; i++)
res.Add(new CompositeType()
{
BoolValue = composite.BoolValue,
StringValue = "Item" + i,
IntValue = i
});
return res.ToArray();
}
Client端則修改如下,改呼叫GetDataUsingDataContract(),透過IntValue要求Server傳回1、16、64、128或256筆結果,取得結果後加總各筆資料的IntValue並檢視最後一筆的StringValue,簡單驗證資料正確性。
staticvoid Main(string[] args)
{
string[] bindingTypes = newstring[] {
"BasicHttpBinding_IService1",
"NetTcpBinding_IService1"
};
foreach (var bindingType in bindingTypes)
{
var tsc = new WcfWas.Service1Client(bindingType);
var compData = new WcfWas.CompositeType()
{
BoolValue = true
};
var counts = newint[] {1, 16, 64, 128, 256};
for (int i = 0; i < counts.Length; i++)
{
compData.IntValue = counts[i];
var res = tsc.GetDataUsingDataContract(compData);
var sum = res.Sum(o => o.IntValue);
var txt = res.Last().StringValue;
Console.WriteLine("Items Count={0}, Sum={1}, String={2}",
res.Length, sum, txt);
}
}
Console.Read();
}
執行結果如下,顯示內容沒什麼意義,期間的資料傳輸量才是重點。
Items Count=1, Sum=0, String=Item0 Items Count=16, Sum=120, String=Item15 Items Count=64, Sum=2016, String=Item63 Items Count=128, Sum=8128, String=Item127 Items Count=256, Sum=32640, String=Item255 Items Count=1, Sum=0, String=Item0 Items Count=16, Sum=120, String=Item15 Items Count=64, Sum=2016, String=Item63 Items Count=128, Sum=8128, String=Item127 Items Count=256, Sum=32640, String=Item255
所以我們開啟MNM,觀察HTTP及TCP傳輸的封包記錄如下。黃底部分是每次Server用來回傳結果的封包,旁邊已加註該次傳回資料筆數方便對照。
BasicHttpBinding
NetTcpBinding
整理結果如下,中間兩欄的數字為HTTP及TCP傳回不同結果筆數產生資料量(Bytes),最後一欄則為TCP資料量除以HTTP資料量的比例。
數字有點可疑,BasicHttpBinding使用XML序列化,NetTcpBinding採二進位序列化,但差距比想像的小很多,且筆數愈多,差距愈小,在256筆時,資料量比例約為10:8,與直覺出入甚大。莫非與HTTP壓縮有關?檢視封包內容,果然看到SOAP XML被IIS壓縮,實際上傳送的不是XML,而是被壓縮過看似亂碼的資料。
為觀察未壓縮的原始資料量,在IIS關閉動態內容壓縮:
重新測試一次,這回可在封包觀察到SOAP XML的模樣,很肥!
而用XML傳256筆資料要花35,118 bytes。
重新統計IIS未壓縮模式下的SOAP XML傳輸,除了單筆資料外,不管筆數多寡,TCP資料量固定維持SOAP XML的15%,符合我們的認知。
實務上,IIS會啟用動態壓縮,最後的實驗純屬好奇並非常態,第一次做的統計才接近真實狀況。也就是說,在IIS壓縮加持下,HTTP+SOAP XML的資料量膨脹不如想像嚴重(例如:256筆時僅多21%),但每次傳輸耗用較多封包數,資料量較大仍是事實,基於效能考量,Intranet的純Windows應用仍應優先考慮TCP。