Рекомендации для служб WCF, используемых как локально, так и удаленно, которые обрабатывают большие файлы в файловой системе? - PullRequest
0 голосов
/ 13 октября 2009

Я создаю службу WCF, которую можно использовать как локально, так и удаленно, и обрабатываю файлы, иногда используя сторонние приложения-компоненты, которые, к сожалению, требуют ввода в качестве пути к реальному файлу в файловой системе, а не .net Stream или чего-либо ещекак это.Существует ли стандартный подход для этой ситуации, с точки зрения того, какими должны быть параметры для контрактных операций и т. Д.?Хотя я полагаю, что это не может быть жизненно важным, поскольку в конечном итоге он должен работать приемлемо как в локальном, так и в удаленном случаях, я бы предпочел, чтобы в локальном случае ему не приходилось читать весь файл из файловой системы, включаясодержание в сообщении, и повторно материализовать его снова в файловой системе, но для удаленного использования это необходимо.Есть ли способ сделать это, например, с помощью типа FSRefDoc, который сериализуется по-разному в зависимости от того, используется ли он локально или удаленно?

edit: уточнить: проблема в том, что я хочу отправлять разные фрагменты информации полностью вдва случая.Если я управляю локальной службой, я могу просто отправить путь к файлу в локальной файловой системе, но если это удаленная служба, я должен сам отправить содержимое файла.Конечно, я могу отправить содержимое в обоих случаях, но это означает, что я теряю производительность в локальном случае.Может, мне не стоит об этом беспокоиться.

Ответы [ 2 ]

1 голос
/ 15 октября 2009

OK

После вашего обновления я бы рассмотрел следующее.

1) Создайте метод, который принимает путь. Выставьте это через привязку именованного канала и используйте это локально. 2) Создайте метод, который принимает файл (поток / байтовый массив и т. Д.). Объясните это с помощью соответствующей привязки (в другой конечной точке) для нелокальных компьютеров (в сценарии локальной сети TCP обычно является лучшим выбором).

Тогда все, что вам нужно сделать, это убедиться, что вы не дублируете ту же бизнес-логику. Итак, в двух словах - создайте 2 разных сервисных интерфейса, 2 разных конечных точки и 2 разных привязки.

0 голосов
/ 14 октября 2009

Ну, вы действительно затрагиваете две отдельные проблемы:

  • доступность локальных и удаленных услуг
  • «обычный» или потоковый сервис (для больших файлов)

В целом, если ваша служба работает за корпоративным брандмауэром в локальной сети, вам следует использовать NetTcpBinding, поскольку он самый быстрый и эффективный. Это быстро и эффективно, потому что он использует двоичное кодирование сообщений (вместо кодирования текстовых сообщений через Интернет).

Если вам необходимо предоставить услугу для «внешнего» мира, вы должны попытаться использовать максимально возможную совместимость привязки, и здесь вы выбираете basicHttpBinding (полностью совместимый - «старые» протоколы SOAP 1.1), который не может быть защищен слишком много, и wsHttpBinding, который предлагает гораздо больше гибкости и возможностей, но менее широко поддерживается.

Поскольку вы можете легко создать один сервис с тремя конечными точками, вы действительно можете создать свой сервис и затем определить эти три конечные точки: одну для локальных клиентов, использующих NetTcpBinding, одну из самых широких доступных с использованием basicHttpBinding, и, опционально, другую с wsHttpBinding.

Это одна сторона истории.

Другое: для ваших «обычных» вызовов службы, обменивающихся несколькими элементами информации (размером до нескольких КБ), вы должны использовать обычное поведение по умолчанию «буферизованной передачи» - сообщение готовится полностью в буфер и отправлено целиком.

Однако для обработки больших файлов лучше использовать режим потоковой передачи - либо «StreamedResponse», если вы хотите, чтобы клиенты могли загружать файлы с вашего сервера, либо «StreamedRequest», если вы хотите, чтобы клиенты могли для загрузки файлов или просто "Потоковое", если вы отправляете файлы в обе стороны.

Таким образом, помимо трех «обычных» конечных точек, у вас должна быть как минимум другая конечная точка для каждой привязки, которая обрабатывает потоковый обмен данными, т.е. выгрузка / загрузка файлов.

Это может показаться множеством разных конечных точек, но это на самом деле не проблема, ваши клиенты могут подключаться к любым конечным точкам, которые им подходят - обычная или потоковая, внутренняя / локальная (netTcpBinding) или внешняя ( basicHttpBinding) по мере необходимости - и в итоге вы напишите код только один раз!

Ах, красота WCF! : -)

Марк

UPDATE:
Хорошо, после вашего комментария я бы сделал следующее:

  • создать ILocalService договор на обслуживание с одним методом GetFile, который возвращает путь и имя файла
  • создать реализацию для сервисного контракта
  • разместить эту службу на конечной точке с netTcpBinding (поскольку она внутренняя, локальная)

[ServiceContract]
interface ILocalService
{
   [OperationContract]
   string GetFile(......(whatever parameters you need here).....);
}

class LocalService : ILocalService
{
   string GetFile(......(whatever parameters you need here).....)
   {
      // do stuff.....
      return fileName;
   }
}

и во-вторых:

  • создать второй контракт на обслуживание IRemoteService с помощью одного метода GetFile, который не возвращает имя файла в виде строки, а вместо этого возвращает поток
  • создать реализацию для сервисного контракта
  • разместить эту службу на конечной точке с basicHttpBinding для использования в Интернете
  • убедитесь, что в конфигурации привязки есть transferMode="StreamedResponse", чтобы включить потоковую передачу файла обратно

[ServiceContract]
interface IRemoteService
{
   [OperationContract]
   Stream GetFile(......(whatever parameters you need here).....);
}

class RemoteService : IRemoteService
{
   Stream GetFile(......(whatever parameters you need here).....)
   {
      // do stuff.....
      FileStream stream = new FileStream(....);
      return stream;
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...