Как улучшить производительность служб данных WCF - PullRequest
23 голосов
/ 12 октября 2010

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

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

Среда:

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

Код:

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

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

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

Результаты:

  • 25 итераций собственного SQL: 436 мс
  • 25 итераций Entity Framework: 656 мс
  • 25 итераций служб данных WCF: 12110 мс

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

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

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

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

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

Ответы [ 8 ]

2 голосов
/ 24 июля 2015

Я увеличил производительность нашего API службы данных WCF на 41%, просто включив сжатие. Это было действительно легко сделать. Перейдите по этой ссылке, которая объясняет, что делать на сервере IIs: Включение динамического сжатия (gzip, deflate) для каналов данных WCF, OData и других пользовательских служб в 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;
}
2 голосов
/ 11 апреля 2011

Ссылка ниже содержит видео, содержащее некоторые интересные тесты WCF и сравнения служб данных WCF и Entity Framework.

http://www.relationalis.com/articles/2011/4/10/wcf-data-services-overhead-performance.html

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

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

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

1 голос
/ 31 октября 2010

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

0 голосов
/ 15 мая 2013

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

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

что попробовать:

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)

0 голосов
/ 31 октября 2010

Как вы проходите эти 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 голосов
/ 26 октября 2010

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

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

var batchResponse = context.ExecuteBatch(batchRequests);

Подробнее см. здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...