2010-10-12 4 views
23

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

Я понимаю, что, поскольку WCF DS является HTTP на основе есть накладные расходы, присущие протоколу, но мои тесты все еще гораздо медленнее, чем хотелось бы ожидать:

Окружающая среда:

  • Все на одной коробке : Четырехъядерный 64-разрядный ноутбук с 4 ГБ оперативной памяти, работающий на W7. Достойная машина.
  • Малая база данных SQL (SQLExpress 2008 R2) с 16 таблицами ... в тестовой таблице содержится 243 строки.
  • Размещено мое тестовое обслуживание в IIS со всеми значениями по умолчанию.

Код:

  • Я создал Entity Framework модель (DataContext) для этой базы данных (складочном Codegen по VS2010).
  • Я создал службу данных на основе этой модели.
  • Я создал клиента, который имеет прямую ссылку на службу (ObjectContext) для этой услуги (фондовый код от VS2010)
  • В клиенте я также могу вызвать модель EF напрямую, а также использовать собственный SQL (ADO .NET SqlConnection)

План тестирование:

  • Каждая итерация соединяется с базой данных (есть возможность повторно использовать соединение), запросы для всех строк в целевой таблице («СОБЫТИЕ»), а затем подсчитывает их (таким образом, заставляя любые отложенные выборки выполняться).
  • Запуск для 25 итераций каждый для собственного SQL (SqlConnection/SqlCommand), Entity Framework (DataContext) и служб данных WCF (ObjectContext).

Результаты:

  • 25 итераций Native SQL: 436ms
  • 25 итераций Entity Framework: 656ms
  • 25 итераций Службы данных WCF: 12110ms

Ouch. Это примерно в 20 раз медленнее, чем EF.

Поскольку службы WCF Data Services являются HTTP, нет возможности повторного использования HTTP-соединений, поэтому клиент вынужден повторно подключаться к веб-серверу для каждой итерации. Но, конечно, здесь происходит нечто большее.

EF сам по себе довольно быстр, и это один и тот же код/​​модель EF повторно используется как для службы, так и для клиентских тестов прямого доступа к EF. Там будут некоторые накладные расходы для Xml-сериализации и десериализации в службе данных, но это многое!?! В прошлом у меня была хорошая производительность с сериализацией Xml.

Я собираюсь запустить некоторые тесты с кодировками JSON и Protocol-Buffer, чтобы узнать, могу ли я повысить производительность, но мне любопытно, есть ли у сообщества какие-либо советы для ускорения этого.

Я не силен с IIS, поэтому, возможно, есть некоторые настройки IIS (кэши, пулы соединений и т. Д.), Которые можно настроить для улучшения этого?

+0

... Интересный ряд мнений, несколько повышающих голосов, и пара любимыха добавляет, но нет ответов. Я открываю щедрость, чтобы вдохнуть еще одну жизнь в этот вопрос. Надеюсь, у кого-то есть ответ. –

+0

Я бы не использовал службы данных WCF, если бы я не планировал подвергать свои данные другим приложениям. Если все работает в одной коробке, почему бы просто не использовать EF напрямую? –

+0

Он не работает на одной коробке. Но источники данных все находятся в (очень большой и международной) корпоративной сети. Я пытаюсь поставить слой обслуживания перед кучей разных источников данных (SQL, XML, плоские файлы и т. Д.), Который изолирует семантику фактической памяти от возможности обнаруживать и запрашивать данные. –

ответ

0

Чтобы устранить большую часть накладных расходов на соединение, вы можете попробовать выполнить все операции с WCF DS, чтобы узнать, имеет ли это значение значительную разницу.

NorthwindEntities context = new NorthwindEntities(svcUri); 
var batchRequests = 
    new DataServiceRequest[]{someCustomerQuery, someProductsQuery}; 

var batchResponse = context.ExecuteBatch(batchRequests); 

Для получения дополнительной информации см. here.

+0

Пакетирование возможно только тогда, когда вы знаете, какие операции вы выполняете заблаговременно. В моем случае мне нужно отреагировать на данные, так, к сожалению, это цикл отображения query-> process-> display-> query-> process->. –

0

Как передать эти 25 итераций для WCF?

var WCFobj = new ...Service(); 
foreach(var calling in CallList) 
    WCFobj.Call(...) 

Если вы вызываете это, это означает, что вы вызываете WCF 25 раз, что потребляет слишком много ресурсов.

Для меня я использовал для создания всего в DataTable и имя таблицы пользователя для хранимой процедуры, которую я вызываю; DataRow - это параметры. При вызове, просто передать DataTable в зашифрованном виде с использованием

var table = new DataTable("PROC_CALLING")... 
... 
StringBuilder sb = new StringBuilder(); 
var xml = System.Xml.XmlWriter.Create(sb); 
table.WriteXml(xml); 
var bytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString()); 
[optional]use GZip to bytes 
WCFobj.Call(bytes); 

Дело в том, вы пройти все 25 вызовов сразу, что может сохранить производительность значительно. Если возвращаемый объект имеет такую ​​же структуру, просто передайте его как DataTable в форме байта и преобразуйте его обратно в DataTable.

Я использовал для реализации этих методов с помощью GZip для модулей данных импорта/экспорта. Передача большого количества байтов делает WCF несчастливым. Это зависит от того, что вы хотите потреблять; вычислительных ресурсов или сетевых ресурсов.

+0

Это специально для службы данных WCF ... проблема очень разрешима для стандартной службы WCF, где лучше контролировать привязку и кодирование сообщений. –

1

Попробуйте установить защиту в «none» в разделе привязки в конфигурации. Это должно значительно улучшить ситуацию.

+0

Хорошая идея ... Я попробую. Конечно, мне все еще нужна безопасность в моем последнем приложении. Но мне любопытно, что такое накладные расходы. –

-1

вещи попробовать: кодирование

1) Результаты: использовать двоичное кодирование вашего WCF канала, если это возможно, см http://msdn.microsoft.com/en-us/magazine/ee294456.aspx - попеременно использовать сжатие: http://programmerpayback.com/2009/02/18/speed-up-your-app-by-compressing-wcf-service-responses/

2) изменить свое поведение экземпляра службы, см http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S6 - попробуйте InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple - если вы можете проверить, что ваша служба построена поточно-безопасным способом.

Что касается вашего теста, я думаю, вы должны имитировать более реалистичную нагрузку (в том числе одновременно работающих пользователей) и игнорировать выбросы, то первый запрос на IIS будет очень медленно (он должен загрузить все DLL)

+1

Похоже, вы даете более общее руководство WCF, чем руководство WCF Data Service. Невозможно (что я знаю) изменить метод кодирования для служб данных WCF ... они должны быть конечными точками HTTP с текстовыми данными. . Формат сериализации может быть либо Xml, либо Json, но он должен быть текстовым. Поэтому сжатие и двоичное кодирование невозможно (я бы хотел). –

+0

Я посмотрю на проявление и согласие. Лучшая практика для WCF утверждает, что PerCall instancing следует использовать, но может работать один экземпляр с множественным параллелизмом. Я сделаю это. –

+0

Что касается эталона, то реализм - это проблема несовместимости между операциями между разными провайдерами. Я уже отбрасываю выбросы ... запуск инициализации занимает около 4-5 секунд. Я могу жить с этим, если это только один раз. –

3

Рассмотрим развертывание, как вместо этого работает служба Windows? У IIS могут быть фильтры ASAPI, правила перезаписи и т. Д., Которые он выполняет. даже если ни один из них не активен, конвейер IIS настолько длинный, что может немного замедлить вас.

служба должна дать вам хорошую основу, как долго он принимает запрос на запуск, упаковываются и т.д., без IIS замедлений

+0

Это хорошая идея. Я также дам этот шанс, когда вернусь к этой части проекта. –

0

WCF DataServices предназначен для предоставления своих клиентов несопоставимых с протоколом OpenData; так как вам не нужно писать/рефакторировать несколько методов веб-службы для каждого запроса на изменение. Я никогда не советую использовать его, если вся система основана на технологии Microsoft. Он предназначен для удаленных клиентов.

0

Я увеличил производительность нашего API обработки данных WCF на 41%, просто включив сжатие. Это было действительно легко сделать. Следуйте этой ссылке, которая объясняет, что делать на вашем сервере IIs: Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

Не забудьте iisReset после вашего изменения!

На стороне клиента:

// This is your context basically, you should have this code throughout your app. 
var context = new YourEntities("YourServiceURL"); 
context.SendingRequest2 += SendingRequest2; 

// Add the following method somewhere in a static utility library 
public static void SendingRequest2(object sender, SendingRequest2EventArgs e) 
{ 
    var request = ((HttpWebRequestMessage)e.RequestMessage).HttpWebRequest; 
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 
} 
Смежные вопросы