Какую политику версии контракта использовать в среде с одним клиентом и несколькими серверами

#.net #wcf #versioning

#.net #wcf #управление версиями

Вопрос:

Я прочитал несколько статей в сети об управлении версиями контрактов WCF. Вот несколько:
Рекомендации по управлению версиями WCF
MSDN: стратегии управления версиями

Теперь я вроде как понимаю основы управления версиями контрактов, но все эти статьи (конечно) в основном предназначены для сред, где есть один сервер и много клиентов, и где клиенты могут быть старше сервера.

В моем случае все наоборот, один клиент и много серверов. Это связано со средой, в которой у меня есть один сервер приложений (клиент), который может взаимодействовать с несколькими рабочими станциями, то есть серверами wcf.
У клиента всегда будет последняя версия, а у серверов может быть более старая версия.

Я планировал внедрить отдельную службу (или просто метод GetVersion в той же службе), чтобы получить версию, поддерживаемую сервером, и в соответствии с этим выбрать правильный контракт в клиенте и выполнить реальный вызов службы.

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

Ответ №1:

Итак, вы выполняете «серверную передачу»? т.Е. Ваше оборудование с фиксированным IP-адресом работает как клиент, а на компьютерах с динамическим IP-адресом запущены ServiceHosts?

Я действительно хотел бы, чтобы существовал «интеллектуальный уровень», который можно было бы просто установить, который занимался бы управлением версиями здесь — но на самом деле волшебной палочки нет. На самом деле IExtensibleObject предназначен только для хранения данных для обхода, но если у сервера есть только старый контракт, то у него также будет только старая реализация, поэтому он не сможет «использовать» эту «расширенную» информацию.

Есть несколько практик, которым вы могли бы следовать. Основное различие заключается в изменении номеров версий или нет… в случае контрактов WCF номер версии как таковой отсутствует, но версия кодируется в пространстве имен / URI контракта.

Если вы не измените пространство имен, то вы, по сути, говорите: «У меня будет один сервис, который НИКОГДА не нарушит обратную совместимость (ну, для версий X)». Затем вы должны внедрить строгую практику разработки, чтобы гарантировать, что никакие методы не будут изменены или удалены, могут быть внесены только дополнения. Это предотвратит отправку клиентом запросов, которые сервер больше не понимает.

Другой подход заключается в изменении URI / пространства имен контракта WCF с каждой ревизией контракта. Затем у вашего «сервера» будет реализация КАЖДОЙ версии контракта, которую вы хотите поддерживать. Если, например, вы поддерживаете клиентов для 3 предыдущих версий, на них может быть запущен последний сервер WCF, но клиент WCF не должен быть старше 3 версий, иначе сервер WCF не поймет запрос (поскольку пространство имен URI / contract не будет существовать). Обычно я выбираю такой подход.

Для этого у меня есть многоуровневый подход

  1. Контракты WCF Это очень статично, изменяется только при крайней необходимости Каждый новый контракт получает новое пространство имен / URI Контракты НЕ наследуются от предыдущей версии — это помешало бы вам отказаться от функциональности.
  2. Реализация службы WCF Эта реализация или реализации — это просто промежуточный уровень — он получает запрос и передает его на соответствующий логический уровень.
  3. Логический уровень / адаптеры если запрос поступил в последнюю версию контракта, он немедленно обрабатывается. если запрос поступил по контракту с предыдущей версией, для этой версии находится адаптер (это может произойти в реализации сервиса, если хотите), и запрос передается адаптеру.

Адаптеры отвечают за получение старого запроса и адаптацию его к пространству имен следующей более новой версии. Это работает в цепочке, например, если запрос получен от клиента версии v1.0 на сервер версии v1.3

 1.0 contract -> 
    1.0 to 1.1 adapter -> 
        1.1 to 1.2 adapter -> 
            1.2 to 1.3 adapter -> 1,3 implementation. (and back if not one-way)
 

Каждый адаптер имеет возможность выполнить подготовить запрос для обработки следующей версией.
Например, в методе 1.1 вы, возможно, ввели требование о передаче «даты запроса», но вы знаете, что можете «сделать наилучшее предположение», поэтому вы добавляете этот аргумент в адаптер 1.0 перед передачей запроса в логику 1.1.

Помните, что все еще возможно вводить требования, которые нельзя «предполагать» или «выполнять по умолчанию» — это нарушало бы договорные изменения, и вы хотели бы делать это только тогда, когда это абсолютно необходимо. Но поскольку вы не связали свои контракты, вы можете некоторое время поддерживать оба метода, а затем удалить старый контракт из поддержки, и все его старые методы исчезнут.

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

Вам также необходимо решить, как долго вы хотите поддерживать старые контракты — чем дольше вы их поддерживаете, тем сложнее становится ваша логика «обработки версий». Приятная особенность объединения этой логики в цепочку в реализации, подобной приведенной выше, заключается в том, что после того, как вы написали слой адаптера для определенной версии, вам никогда не придется возвращаться к нему.

Надеюсь, это дало вам пищу для размышлений.