Подтвердить что ты не робот

Как улучшить производительность служб данных WCF

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

Я понимаю, что, поскольку 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 итераций каждый для собственного SQL (SqlConnection/SqlCommand), Entity Framework (DataContext) и служб данных WCF (ObjectContext).

Результаты:

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 3

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

Ответ 4

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

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

var batchResponse = context.ExecuteBatch(batchRequests);

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

Ответ 5

Как вы передаете эти 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 несчастливым. Это зависит от того, что вы хотите потреблять; вычислительных ресурсов или сетевых ресурсов.

Ответ 6

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

Ответ 7

Я увеличил производительность нашего 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;
}

Ответ 8

вещи, которые нужно попробовать:

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 - if вы можете проверить, что ваша служба построена поточно-безопасным способом.

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