Thursday, October 21, 2010

WCF: передача XML и расход памяти

Как я писал недавно - http://devlanfear.com/perexod-s-asp-net-web-services-na-wcf/ - мы перевели свой проект с ASP.NET веб-сервисов на WCF.  В процессе перевода столкнулись с проблемой – WCF не хотел сериализовать поле типа XmlNode, пришлось искать пути обхода этой проблемы. Первый вариант был – использовать XmlElement (наследник XmlNode), который сериализуется без проблем. Но при тестировании были обнаружены некоторые нюансы: сериализация XML, имеющим в себе ProcessingInstruction, упорно не работала,к тому же при передаче выходной XML иногда получался кривой –  появлялись дополнительные ChildNode (типа Whitespace) для каждого переноса строк, и не только.
В итоге было отдано предпочтение работе со строками:
public static XmlNode ToXml(string xml)
      {
          XmlDocument doc = new XmlDocument();
          doc.LoadXml(xml);
          return doc.DocumentElement;
      }
      public static string FromXml(XmlNode xml)
      {
          if (xml == null) return string.Empty;
          return xml.OuterXml;
  }
Конвертация XML в string и обратно выполнялась вышеописанным способом.
Но в итоге столкнулись с целой вереницей проблем: при больших нагрузках на сервисы выпадало исключение OutOfMemory. Причина была совершенно непонятна, т.к. при мониторинге не было замечено ни утечек памяти, ни заметного причинного роста. По данным из EventLog’а ошибка происходила при обращении к свойству OuterXml объекта типа XmlNode, а в итоге здесь - System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity)
Read more: -2701">.NET разработка от devlanfear