简体   繁体   English

c#WebService压缩

[英]c# WebService Compression

I have an application that uses WebServices to send database records (as an array) to the client, yet even when sending only 1000 records it seems to be really slow. 我有一个使用WebServices将数据库记录(作为数组)发送到客户端的应用程序,但是即使仅发送1000条记录,它似乎也确实很慢。

The server is running on an IIS 7 and the client is a WPF application. 服务器在IIS 7上运行,客户端是WPF应用程序。 Basically, how do I speed this up. 基本上,我如何加快速度。 Do I have to write a custom compression class or code? 我是否必须编写自定义压缩类或代码? Is there just a setting I turn on/off on the IIS server and/or the client config files? 是否只有我在IIS服务器和/或客户端配置文件上打开/关闭的设置? Right now it takes about 4-7 seconds to return these 1000 records. 现在返回这1000条记录大约需要4-7秒。 So when we tie into the tables that can possibly return 10,000 - 40,000 records I don't want the user to sit there for minutes waiting for data. 因此,当我们绑定可能返回10,000-40,000条记录的表时,我不希望用户坐在那里等待几分钟的数据。

Here's an example of the code: 这是代码示例:

Foo.svc: 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: 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: 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);
        }
    }
}

In all likelihood, your performance bottleneck is the serialization and deserialization of the SelectRecordsResponse object. 您的性能瓶颈极有可能是SelectRecordsResponse对象的序列化和反序列化。 I can offer several ways to make it faster, in order from least to most difficult: 我可以提供几种方法来加快速度,从最小到最难:

  1. Use the NETTCP protocol 使用NETTCP协议
  2. Use binary message encoding. 使用二进制消息编码。
  3. Make sure you're using DataContract Serializer instead of Xml Serializer 确保您使用的是DataContract Serializer而不是Xml Serializer
  4. Write a custom serializer - this should be your last resort but will probably allow you to make the largest performance improvement 编写自定义序列化程序 - 这应该是您的最后手段,但可能会让您获得最大的性能提升

Have you considered using Microsoft Synchronization Services which works over WCF? 您是否考虑过使用适用于WCF的Microsoft同步服务

I have used it in the past to sync data down to the client and up to the server with a similar number of records. 我过去曾使用它来将数据同步到客户端,直到具有相似数量记录的服务器。 It allows you to filter data based on certain criteria and allow for incremental downloading. 它允许您根据特定条件过滤数据并允许增量下载。

However even when using Sync Services I did notice a massive slow down when syncing large amounts of data. 但是,即使使用同步服务,我也发现在同步大量数据时会出现大幅减速。 This is because by default the data is serialized to Xml, I resolved this using the binary encoder instead. 这是因为默认情况下数据被序列化为Xml,我使用二进制编码器解决了这个问题。

It seems that the best way to reduce down the alloted time was a suggestion in the comments, that is paginating the data so that not as much is sent down. 减少分配时间的最好方法似乎是在注释中提出建议,即对数据进行分页,以便减少发送的时间。 I do agree using something other than XML serialization will speed things up, but not enough. 我同意使用XML序列化之外的东西会加快速度,但还不够。 Also, using other serializations wasn't acceptable since we had to go with an interop serialization method, in case we ever come out with a Java client instead. 此外,使用其他序列化是不可接受的,因为我们不得不使用互操作序列化方法,以防我们使用Java客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM