2010-11-03 72 views
0

我有一個應用程序使用WebServices向客戶端發送數據庫記錄(作爲數組),但即使只發送1000條記錄,它似乎很慢。c#WebService壓縮

服務器在IIS 7上運行,客戶端是WPF應用程序。基本上,我如何加快速度。我是否必須編寫自定義壓縮類或代碼?在IIS服務器和/或客戶端配置文件中只有一個設置是打開/關閉的?現在需要大約4-7秒才能返回這1000條記錄。因此,當我們將可能返回10,000到40,000條記錄的表綁定在一起時,我不希望用戶在那裏等待數據等待幾分鐘。

下面的代碼的一個例子:

Foo.svc:

namespace Foo.Server 
{ 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public sealed class FooService : IFoo 
    { 
     public SelectRecordsResponse SelectRecords(SelectRecordsRequest request) 
     { 
      //I tested to ensure that this isn't my bottleneck 
      FooBar[] records = ...; //Stores 1000 records 

      return new SelectRecordsResponse(records); 
     } 
    } 
} 

FooCommon.cs:

namespace Foo 
{ 
    [ServiceContract(Namespace = "http://www.company.com/Services/Foo", ConfigurationName = "IFoo")] 
    [ServiceKnownType(typeof(AbstractEntity))] 
    [XmlSerializerFormat(SupportFaults = true, Style = OperationFormatStyle.Document, Use = OperationFormatUse.Literal)] 
    public interface IFoo 
    { 
     [OperationContract(Action = "http://www.company.com/Services/Foo/SelectRecords", 
          ReplyAction = "http://www.company.com/Services/Foo/SelectRecordsReply", 
          Name = "SelectRecords")] 
     [ServiceKnownType(typeof(FooBar))] 
     [return: MessageParameter(Name = "Response")] 
     SelectRecordsResponse SelectRecords([MessageParameter(Name = "Request")]SelectRecordsRequest request); 
    } 

    [MessageContract(WrapperName = "SelectRecordsRequest", WrapperNamespace = "http://www.company.com/Services/Foo/", IsWrapped = true)] 
    public sealed class SelectRecordsRequest 
    { 
     public SelectRecordsRequest() 
     { 
     } 
    } 

    [MessageContract(WrapperName = "SelectRecordsResponse", WrapperNamespace = "http://www.company.com/Services/Foo/", IsWrapped = true)] 
    public sealed class SelectRecordsResponse 
    { 
     public SelectRecordsResponse() 
     { 
      Init(); 
     } 

     public SelectRecordsResponse(FooBar[] records = null) 
     { 
      Init(records); 
     } 

     private void Init(FooBar[] records = null) 
     { 
      Records = records ?? new FooBar[0]; 
     } 

     [MessageBodyMember(Namespace = "http://www.company.com/Services/Foo/", Order = 0, Name = "Records")] 
     [XmlArray(ElementName = "SelectRecordsArray", Form = XmlSchemaForm.Qualified)] 
     [XmlArrayItem(typeof(FooBar), ElementName = "SelectRecordsFooBar", Form = XmlSchemaForm.Qualified, IsNullable = true)] 
     private FooBar[] Records { get; set; } 
    } 
} 

FooClient.cs:

namespace Foo.Client 
{ 
    public interface IFooChannel : IFoo, IClientChannel 
    { 
    } 

    public sealed class FooClient : ClientBase<IFoo>, IFoo 
    { 
     public FooClient(String endpointConfigurationName) : 
      base(endpointConfigurationName) 
     { 
     } 

     public FooBar[] SelectRecords() 
     { 
      SelectRecordsRequest request = new SelectRecordsRequest(); 
      SelectRecordsResponse response = ((IFoo)(Client)).SelectRecords(request); 

      return response.Records; 
     } 

     SelectRecordsResponse IFoo.SelectRecords(SelectRecordsRequest request) 
     { 
      return Channel.SelectRecords(request); 
     } 
    } 
} 
+1

如果查詢向客戶端返回40000條記錄,則查詢很可能是錯誤的。在將結果返回給客戶端之前,可能應該對結果進行彙總或過濾。 – 2010-11-03 15:15:32

+0

你應該實現「分頁」。你永遠無法*一舉返回40,000條記錄。 – 2010-11-03 15:41:32

+0

我確實正在過濾和分頁,但有一些客戶希望每個記錄一次在數據網格中可見。無論哪種方式,100個記錄或40,000我仍然需要實施某種壓縮。 – 2010-11-03 15:50:19

回答

0

看來,最好的減少分配時間的方式是在評論中提出的一個建議,即對數據進行分頁,以減少分發數量。我確實同意使用XML序列化以外的東西會加快速度,但還不夠。此外,使用其他序列化是不可接受的,因爲我們必須採用互操作序列化方法,以防出現Java客戶端。

0

你有沒有考慮過使用Microsoft Synchronization Services這對WCF有效?

我已經在過去使用它將數據同步到客戶端,並將數據同步到具有相似記錄數的服務器。它允許您根據特定標準過濾數據並允許增量下載。

但是,即使在使用同步服務時,在同步大量數據時,我的確注意到速度很慢。這是因爲默認情況下數據被序列化爲Xml,我使用binary encoder來解決這個問題。

2

很可能,您的性能瓶頸是SelectRecordsResponse對象的序列化和反序列化。我可以從最低到最高難度提供多種方式,使其更快,依次是:

  1. 使用NETTCP協議
  2. 使用二進制消息編碼。
  3. 確保您使用DataContract串行而不是XML串行
  4. custom serializer - 這應該是您的最後手段,但可能讓你做出最大的性能改進