У меня есть случай, когда мне нужно передать большое количество сериализованных графов объектов (через NetDataContractSerializer ), используя WCF, используя wsHttp.Я использую безопасность сообщений и хотел бы продолжать это делать.Используя эту настройку, я хотел бы перенести сериализованный граф объектов, который иногда может приближаться к 300 МБ или около того, но когда я пытаюсь это сделать, я начинаю видеть исключение типа System.InsufficientMemoryException.
После небольшого исследования выясняется, что по умолчанию в WCF результат вызова службы содержится в одном сообщении по умолчанию, которое содержит сериализованные данные, и эти данные по умолчанию буферизуются на сервере до полногосообщение полностью написано.Таким образом, исключение памяти вызвано тем фактом, что серверу не хватает ресурсов памяти, которые ему разрешено выделять, поскольку этот буфер заполнен.Две основные рекомендации, с которыми я столкнулся, - это использование потоковой передачи или разбиения на фрагменты для решения этой проблемы, однако мне не ясно, что это включает и возможно ли какое-либо решение с моей текущей настройкой (wsHttp / NetDataContractSerializer / Message Security).До сих пор я понимаю, что использование безопасности потоковых сообщений не сработает, поскольку шифрование и дешифрование сообщений должны работать со всем набором данных, а не с частичным сообщением.Чанкинг, однако, звучит так, как будто это возможно, однако мне не ясно, как это будет сделано с другими ограничениями, которые я перечислил.Если бы кто-нибудь мог предложить какое-то руководство относительно того, какие решения доступны и как его реализовать, я был бы очень признателен.
Я должен добавить, что в моем случае я действительно не беспокоюсь о совместимости с другими клиентами, так как мывладеть и контролировать каждую сторону связи и использовать шаблон общего интерфейса для данных, передаваемых любой стороне.Так что я открыт для любой идеи, которая вписывается в ограничения использования wsHttp с защитой сообщений для передачи графов объектов, сериализованных с использованием NetDataContractSerializer, и я предпочитаю решение, при котором мне не нужно резко менять существующие сервисы и окружающую инфраструктуру.
Связанные ресурсы:
Меня также интересует любой тип сжатия, который можно выполнить наэти данные, но, похоже, мне лучше всего сделать это на транспортном уровне, как только я смогу перейти на .NET 4.0, чтобы клиент автоматически поддерживал заголовки gzipесли я правильно понимаю.
Обновление (2010-06-29):
Немного истории о том, как я пришел к выводу, что слишком большое буферизованное сообщение вызывало мою проблему.Первоначально я видел CommunicationException ниже во время тестирования.
Базовое соединение было закрыто: соединение было неожиданно закрыто.
В конце концов после запуска этого ивыполняя еще несколько журналов, я обнаружил базовое исключение InsufficientMemoryException , которое вызывало проблему с указанным сообщением.
Не удалось выделить буфер управляемой памяти в 268435456 байт.Объем доступной памяти может быть низким.
, который возник из следующего метода.
System.ServiceModel.Diagnostics.Utility.AllocateByteArray (размер Int32)
Другими словами, сбой произошел из-за выделения массива. При записи одних и тех же данных, сериализованных на диск, это занимает около 146 МБ, и если я урежу их вдвое, я перестану получать сообщение об ошибке, однако я больше не копался в конкретном пороговом значении, которое нарушает мой буфер, и в зависимости от того, относится ли оно к моей системе или нет.
Обновление (2010-12-06):
Полагаю, на данный момент я ищу уточнения для следующего. Насколько я понимаю, по умолчанию с WCF wsHttp с защитой сообщений, что целое сообщение (как правило, весь набор данных, которые я возвращаю) необходимо буферизовать на сервере, прежде чем ответ будет отправлен обратно клиенту, что вызовет мои проблемы.
Возможные решения:
- Ограничение размера данных - с помощью некоторой формы сжатия, кодирования или ограничения фактических данных, возвращаемых с использованием какого-либо метода, подобного поисковому вызову, чтобы избежать использования максимальной емкости исходящего буфера.
- Потоковая передача - позволяет передавать большие объемы данных через WCF потоковым способом, однако это несовместимо с wsHttp или MessageSecurity, поскольку эти методы требуют буферизации всех данных.
- Chunking Channel - позволяет разбивать данные на отдельные сообщения, но на данный момент я не уверен в ограничениях, которые это имеет для дизайна контракта на обслуживание, и могу ли я все еще использовать wsHttp с привязкой сообщений.
Ограничение данных, которые я могу вернуть, работает только до определенного момента, и, как и при использовании параметра «Потоковая передача», эти параметры требуют кодирования большей части работы более низкого уровня вне вызовов службы WCF. Поэтому я думаю, что мне нужно знать, может ли любая возможная реализация канала чанкинга обойти большие проблемы с сообщениями, позволяя разбивать один набор данных на отдельные сообщения на сервере и затем объединять их на клиенте в таким образом, что мне не нужно менять интерфейс / форму существующих сервисных контрактов и таким образом, что процесс в значительной степени скрыт от клиентской и серверной частей каждой реализации сервиса, все еще используя защиту сообщений и wsHttp. Если канал chunking потребует, чтобы я переписал свои сервисные контракты, чтобы показать потоки, то я не вижу, как это на самом деле отличается от потокового решения. Если кто-то может просто ответить на эти вопросы для меня, я награжу их премией и отмечу ее как ответ.