c#WebService压缩

时间:2010-11-03 15:12:09

标签: c# web-services iis-7 .net-4.0 compression

我有一个使用WebServices将数据库记录(作为数组)发送到客户端的应用程序,但即使只发送1000条记录,它似乎也很慢。

服务器在IIS 7上运行,客户端是WPF应用程序。基本上,我如何加快速度。我是否必须编写自定义压缩类或代码?是否只有我在IIS服务器和/或客户端配置文件上打开/关闭的设置?现在返回这1000条记录大约需要4-7秒。因此,当我们绑定到可能返回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);
        }
    }
}

3 个答案:

答案 0 :(得分:2)

很可能,您的性能瓶颈是SelectRecordsResponse对象的序列化和反序列化。我可以提供几种方法来加快速度,从最小到最困难:

  1. 使用NETTCP协议
  2. 使用二进制邮件编码。
  3. 确保您使用的是DataContract Serializer而不是Xml Serializer
  4. 写一个custom serializer - 这应该是你的最后手段,但可能会让你做出最大的性能提升

答案 1 :(得分:0)

您是否考虑使用适用于WCF的Microsoft Synchronization Services

我过去曾使用它将数据同步到客户端,直到具有相似数量记录的服务器。它允许您根据特定条件过滤数据,并允许增量下载。

然而,即使使用同步服务,我也注意到在同步大量数据时会出现大幅减速。这是因为默认情况下数据被序列化为Xml,我使用binary encoder解决了这个问题。

答案 2 :(得分:0)

似乎减少分配时间的最佳方法是在评论中提出建议,即对数据进行分页,以便减少发送量。我同意使用XML序列化之外的东西会加快速度,但还不够。此外,使用其他序列化是不可接受的,因为我们不得不使用互操作序列化方法,以防我们改为使用Java客户端。