c # Сжатие WebService - PullRequest
       31

c # Сжатие WebService

0 голосов
/ 03 ноября 2010

У меня есть приложение, которое использует WebServices для отправки записей базы данных (в виде массива) клиенту, но даже при отправке только 1000 записей это выглядит очень медленно.

Сервер работает на 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);
        }
    }
}

Ответы [ 3 ]

2 голосов
/ 04 ноября 2010

По всей вероятности, узким местом вашей производительности является сериализация и десериализация объекта SelectRecordsResponse.Я могу предложить несколько способов сделать это быстрее, от минимального до самого сложного:

  1. Использовать протокол NETTCP
  2. Использовать двоичное кодирование сообщений.
  3. Убедитесь, чтовы используете DataContract Serializer вместо Xml Serializer
  4. Напишите пользовательский сериализатор - это должно быть вашим последним средством, но, вероятно, позволит вам добиться наибольшего улучшения производительности
0 голосов
/ 18 ноября 2010

Кажется, что лучшим способом сократить выделенное время было предложение в комментариях, которое разбивает данные на страницы, чтобы не так много передавалось.Я согласен, что использование чего-то кроме XML-сериализации ускорит процесс, но этого недостаточно.Кроме того, использование других сериализаций было неприемлемо, поскольку нам приходилось использовать метод сериализации взаимодействия, на случай, если мы когда-нибудь выпустим клиент Java.

0 голосов
/ 03 ноября 2010

Рассматривали ли вы возможность использования Microsoft Synchronization Services , которая работает через WCF?

В прошлом я использовал это для синхронизации данных до клиента и до сервера с аналогичным номеромзаписей.Он позволяет фильтровать данные на основе определенных критериев и допускает добавочную загрузку.

Однако даже при использовании служб синхронизации я заметил значительное замедление при синхронизации больших объемов данных.Это связано с тем, что по умолчанию данные сериализуются в Xml, я решил эту проблему с помощью двоичного кодировщика .

...