Как повысить производительность служб данных 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 Data Services (ObjectContext).

Результаты:

  • 25 итераций собственного SQL: 436 мс
  • 25 итераций Entity Framework: 656 мс
  • 25 итераций WCF Data Services: 12110 мс

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

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

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

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

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


person Simon Gillbee    schedule 12.10.2010    source источник
comment
Интересно ... количество просмотров, несколько голосов за и пара добавленных в избранное, но нет ответов. Я назначаю награду за это, чтобы вдохнуть еще немного жизни в этот вопрос. Надеюсь, у кого-то есть ответ.   -  person Simon Gillbee    schedule 25.10.2010
comment
Я бы не стал использовать WCF Data Services, если не планировал предоставлять свои данные другим приложениям. Если все работает на одном компьютере, почему бы просто не использовать EF напрямую?   -  person John Bledsoe    schedule 25.10.2010
comment
Он не работает на одном компьютере. Но все источники данных находятся в (очень большой и международной) корпоративной сети. Я пытаюсь поставить уровень обслуживания перед кучей различных источников данных (SQL, XML, плоские файлы и т. Д.), Который изолирует фактическую семантику хранилища от возможности обнаруживать и запрашивать данные.   -  person Simon Gillbee    schedule 26.10.2010
comment
Как вы это тестируете? Однажды я тестировал веб-сервис в IE. Накладные расходы браузера на отображение данных составляли около 80%.   -  person CodingBarfield    schedule 01.11.2010
comment
Сколько данных вы используете для этого теста, возможно, это пропускная способность.   -  person WeNeedAnswers    schedule 02.11.2010
comment
@Barfieldmv - я не использую IE ... просто стандартный клиент консольного приложения, к которому я подключаюсь и запускаю запрос в блоке StopWatch.   -  person Simon Gillbee    schedule 06.11.2010
comment
@WeNeedAnswers - не так много данных, всего несколько 100 КБ (менее МБ). И все это локально, поэтому сеть не играет большой роли.   -  person Simon Gillbee    schedule 06.11.2010
comment
несколько XML-файлов размером 100 КБ в большой объем данных.   -  person Alex Lo    schedule 08.11.2010
comment
Вы можете что-нибудь сказать по этому поводу? Вы наконец отказались от WCF DS для обычной службы WCF с более настраиваемыми параметрами? Может быть, вам удалось достаточно оптимизировать, чтобы сохранить его? Мне действительно интересно ваше мнение по этому поводу. Спасибо!   -  person Nock    schedule 29.12.2012


Ответы (8)


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

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

person Jeremy Massel    schedule 08.11.2010
comment
Это хорошая идея. Я также попробую это сделать, когда вернусь к этой части проекта. - person Simon Gillbee; 10.11.2010

По ссылке ниже есть видео с некоторыми интересными тестами WCF и сравнениями между службами данных WCF и Entity Framework.

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

person Steve the coder    schedule 11.04.2011

Я увеличил производительность нашего API службы данных WCF на 41%, просто включив сжатие. Сделать это было действительно легко. Перейдите по этой ссылке, где объясняется, что делать на вашем сервере IIs: Включение динамического сжатия (gzip) для WC Каналы данных, 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;
}
person Frank.Germain    schedule 24.07.2015

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

person fhj    schedule 31.10.2010
comment
Хорошая идея ... Я попробую. Конечно, мне все еще нужна безопасность в моем последнем приложении. Но мне любопытно, каковы накладные расходы. - person Simon Gillbee; 06.11.2010

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

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

var batchResponse = context.ExecuteBatch(batchRequests);

Дополнительную информацию см. здесь.

person ntziolis    schedule 26.10.2010
comment
Пакетирование возможно только в том случае, если вы заранее знаете, какие операции выполняете. В моем случае мне нужно реагировать на данные, поэтому, к сожалению, это цикл запроса- ›процесс-› дисплей- ›запрос-› процесс- ›дисплей. - person Simon Gillbee; 06.11.2010

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

person Amit Kr    schedule 15.05.2013

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

person Bonshington    schedule 31.10.2010
comment
Это специально для службы данных WCF ... проблема очень разрешима для стандартной службы WCF, где есть лучший контроль привязки и кодирования сообщений. - person Simon Gillbee; 06.11.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-answers/

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

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

person Alex Lo    schedule 08.11.2010
comment
Похоже, вы даете более общее руководство WCF, чем конкретное руководство по WCF Data Service. Невозможно (насколько я знаю) изменить метод кодирования для WCF Data Services ... они должны быть конечными точками HTTP с текстовыми данными ... формат сериализации может быть Xml или Json, но должен быть текстовым. Таким образом, сжатие и двоичное кодирование невозможно (я бы хотел, чтобы это было). - person Simon Gillbee; 10.11.2010
comment
Я посмотрю на инстансы и конкурентность. Лучшая практика для WCF гласит, что следует использовать экземпляры PerCall, но также может работать один экземпляр с множественным параллелизмом. Я попробую. - person Simon Gillbee; 10.11.2010
comment
Что касается эталонного теста, реализм - меньшая проблема, чем согласованность операций между разными поставщиками. Я уже отбрасываю выбросы ... запуск сам по себе занимает около 4-5 секунд. Я смогу с этим жить, если только разок. - person Simon Gillbee; 10.11.2010
comment
сжатие работает с текстовыми ответами, очевидно, что двоичное кодирование отсутствует. все XML-данные, о которых вы говорите, займут много времени. PerCall означает, что вам нужно каждый раз создавать экземпляры подключений к БД, Single означает, что они кэшируются (опять же, безопасность потоков будет проблемой). - person Alex Lo; 11.11.2010