Потоковые заголовки записи занимают слишком много времени WCF

Аналогичный вопрос задан в NewRelic stream & writeHeaders.

Я профилирую свои WCF сервисы в New Relic. Существует служба WCF, которая вызывает другую службу WCF. Теперь я полагаю, что при вызове другой службы WCF, когда она создает запрос, где-то внутренний процесс записывает заголовки в поток запросов, который несколько раз замедляется. Следы, которые я нашел в New Relic, говорят мне, что для определенного метода одной из моих служб WCF, который вызывает метод моей другой WCF службы, требуется около 50-60 секунд, из которых 95-100 % времени потребляется System.Net.ConnectStream. Написать заголовки.

Stream[url of WCF service/soap]: WriteHeaders -> 99.78 % time (approx 49 seconds).

Я не понимаю, что это такое и как уменьшить это время?

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

Пожалуйста, дайте мне знать ваши предложения.


person Deeps    schedule 16.04.2013    source источник
comment
Привет @Deeps, тебе повезло с этой проблемой? Мы также столкнулись с точно такой же проблемой. Если да, не могли бы вы поделиться тем же. ТИА   -  person texens    schedule 25.06.2013
comment
Привет texens, Извините за поздний ответ. Нет, я не получил никакого решения до сих пор.   -  person Deeps    schedule 09.09.2013


Ответы (2)


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

Я провел последний год, работая над проектом, похожим на то, чем вы занимаетесь. Разница между потоковой передачей и буферизацией заключается в следующем:

Потоковая передача считывает (из источника), а затем записывает (в целевой объект) данные в интерактивном процессе, над которым у вас нет большого контроля. Если исходный файл большой (например, гигабайт или больше), запрос/ответ WCF будет повторяться дюжину или более раз между клиентом и хостом, прежде чем запрос будет завершен.

Буферизация, с другой стороны, накапливает все содержимое целевого файла ДО заполнения запроса и его отправки на хост, тем самым ускоряя процесс. А поскольку снижение производительности, связанное с буферизацией (время, необходимое для накопления байтов в памяти), ложится на клиента, обычно это не проблема.

Таким образом, при буферизации данных от клиента ваш хост вы получите один Http-запрос с полным массивом байтов (скажем), который готов к переупаковке в запрос, который вы передаете на второй, целевой хост WCF. В этот момент, опять же, у вас есть выбор между буферизацией и потоковой передачей. На хосте, если производительность имеет значение, потоковая передача запроса на второй хост улучшит вашу масштабируемость, но (опять же) может снизить вашу производительность.

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

    With binding
      .TransferMode =TransferMode.Buffered 'instead of Transfermode.Streamed                                                              
      .MessageEncoding = WSMessageEncoding.Text
      .TextEncoding = System.Text.Encoding.UTF8
      .MaxReceivedMessageSize = Integer.MaxValue
      .ReaderQuotas.MaxArrayLength = Integer.MaxValue
      .ReaderQuotas.MaxBytesPerRead = Integer.MaxValue
      .ReaderQuotas.MaxDepth = Integer.MaxValue
      .ReaderQuotas.MaxNameTableCharCount = Integer.MaxValue
      .ReaderQuotas.MaxStringContentLength = Integer.MaxValue
      .MaxBufferSize = Integer.MaxValue
      .MaxBufferPoolSize = Integer.MaxValue

На принимающей стороне:

With binding
      .TransferMode = TransferMode.Buffered
      .MaxReceivedMessageSize = Integer.MaxValue
person Brian    schedule 19.04.2013
comment
Привет, Брайан, я не транслирую большие файлы или что-то в этом роде. Это просто служба WCF, которую я запрашиваю. Я добавил ссылку на службу службы WCF в свой проект, который также является службой WCF. Теперь у меня есть метод в моей службе как GetMerchantData(string param1), который получает некоторые значения из моей базы данных, а затем вызывает метод добавленной ссылки на службу: GetMerchantStoreData(string param1, string param2, string param3). Запрос выглядит так: - person Deeps; 22.04.2013
comment
Клиент MyServiceRefClient = новый MyServiceRefClient(); результат var = client.GetMerchantStoreData(param1, param2, param3); а затем я возвращаю этот результат из моей службы. Этот объект результата содержит 12 свойств. Я не думаю, что это большие данные или какая-либо потоковая передача. Я думаю, что это связано с написанием некоторых заголовков по умолчанию при выполнении запроса к службе wcf, размещенной на ssl. Но я не могу понять, что я могу сделать, чтобы сократить это время. Потому что я нигде не писал эту строку Stream[url службы/мыла WCF]: WriteHeaders в моем коде. Спасибо. - person Deeps; 22.04.2013
comment
Я понимаю. Извините, я не мог помочь дальше. - person Brian; 24.04.2013

Я видел то же самое раньше, когда служба, которую вы вызываете, зависает или перегружена слишком большим количеством одновременных подключений. Если проблема связана с первым, профилирование вашей службы WCF может помочь определить основную причину — возможно, она медленно отвечает из-за доступа к базе данных или какого-либо другого процесса, связанного с вводом-выводом. Если проблема возникнет позже, ее можно решить, настроив производительность службы (http://msdn.microsoft.com/en-us/library/ee377061(v=bts.10).aspx)

Это также может проявляться как «BeginRequest» для приложения ASP.NET в New Relic. В редких случаях BeginRequest или WriteHeaders означают, что проблема действительно связана с отправкой самих данных, хотя это может быть, если у вас большие полезные нагрузки, но при обычных вызовах, когда передаваемых данных мало, появится проблема с медленным временем подключения или медленным ответом. в этих двух областях.

person seanmcelroy    schedule 23.07.2013