Каковы Ваши лучшие практики Управления версиями WebService?

У нас есть 2 отдельных продукта, которые должны общаться друг с другом через веб-сервисы. Что лучшая практика должна поддержать versioining API?

У меня есть эта статья с 2004, утверждая, что нет никакого фактического стандарта и только лучших практик. Какие-либо лучшие решения? Как Вы решаете управление версиями WS?

Описание проблемы

Система A

Клиент

class SystemAClient{
    SystemBServiceStub systemB;
    public void consumeFromB(){
        SystemBObject bObject = systemB.getSomethingFromB(new SomethingFromBRequest("someKey"));

    }
}

Обслуживание

class SystemAService{
    public SystemAObject getSomethingFromA(SomethingFromARequest req){
        return new SystemAObjectFactory.getObject(req);
    }
}

Передаваемый объект

Версия 1

class SystemAObject{
     Integer id;
     String name;
     ... // getters and setters etc;
}

Версия 2

class SystemAObject{
     Long id;
     String name;
     String description;
     ... // getters and setters etc;
}

Объект запроса

Версия 1

class SomethingFromARequest {
     Integer requestedId;
     ... // getters and setters etc;

}

Версия 2

class SomethingFromARequest {
     Long requestedId;
     ... // getters and setters etc;

}

Система B

Клиент

class SystemBClient{
    SystemAServiceStub systemA;
    public void consumeFromA(){
        SystemAObject aObject = systemA.getSomethingFromA(new SomethingFromARequest(1));
        aObject.getDescription() // fail point
        // do something with it...
    }
}

Обслуживание

class SystemBService{
    public SystemBObject getSomethingFromB(SomethingFromBRequest req){
        return new SystemBObjectFactory.getObject(req);
    }
}

Передаваемый объект

Версия 1

class SystemBObject{
     String key;
     Integer year;
     Integer month;
     Integer day;

     ... // getters and setters etc;
}

Версия 2

class SystemBObject{
     String key;
     BDate date;
     ... // getters and setters etc;
}

class BDate{
     Integer year;
     Integer month;
     Integer day;
     ... // getters and setters etc;

}

Объект запроса

Версия 1

class SomethingFromBRequest {
     String key;
     ... // getters and setters etc;
}

Версия 2

class SomethingFromBRequest {
     String key;
     BDate afterDate;
     BDate beforeDate;
     ... // getters and setters etc;
}

Подводят сценарии

Если Система, клиент версии 1 называет Систему B обслуживанием версии 2, на которой это может потерпеть неудачу:

  • недостающие методы на SystemBObject (getYear(), getMonth(), getDay())
  • Неизвестный тип BDate

Если Система, клиент версии 2 называет Систему B обслуживанием версии 1, на которой это может потерпеть неудачу:

  • Неизвестный тип BDate на SomethingFromBRequest (Клиент использует более новый объект запроса B, который версия 1 B не признает),
  • Если Система, клиент достаточно умен, чтобы использовать версию 1 объекта запроса, она может потерпеть неудачу на недостающих методах на SystemBObject объект (getDate())

Если Система B клиент версии 1 называет Систему обслуживанием версии 2, это может потерпеть неудачу на:

  • Напечатайте несоответствие или переполнение на SystemAObject (возвращенный Long но ожидаемый Integer)

Если Система B клиент версии 2 называет Систему обслуживанием версии 1, это может потерпеть неудачу на:

  • Напечатайте несоответствие или переполнение на SystemARequest (запрос Long вместо Integer)
  • Если запрос прошел так или иначе, бросая проблемы (окурок Long но обслуживание возвращается Integer не nessecarily совместимый во всех внедрениях WS)

Возможные решения

  1. Используйте числа когда продвигающиеся версии: например. SystemAObject1, SystemBRequest2 и т.д., но это пропускает API для соответствия источнику / целевая версия
  2. В подписи передайте XML и не объекты (фу, проход избежал XML в XML, двойное преобразование в последовательную форму, десериализация / парсинг, не разобрав),
  3. Другое: например, Документ / буквальный / у WS-I есть средство?

19
задан Eran Medan 20 January 2010 в 13:27
поделиться

4 ответа

Я предпочитаю метод SalesForce.com версию. Каждая версия веб-сервисов получает отчетливый URL в формате:

http://api.salesforce.com/{version}/{serviceName}

, поэтому у вас будет URL-адреса веб-сервисов, похожее на:

http://api.salesforce.com/14/Lead

http://api.salesforce.com/15/Lead

и так далее ...

с этим методом, вы получаете преимущества из:

  1. Вы всегда знаете, с какой версией вы разговариваете.

  2. Обратная совместимость поддерживается.

  3. Вам не нужно беспокоиться о проблемах на зависимости. Каждая версия имеет полный набор услуг. Вам просто нужно убедиться, что вы не смешиваете версии между звонками (но это до потребителя сервиса, а не как разработчик).

23
ответ дан 30 November 2019 в 03:52
поделиться

Решение состоит в том, чтобы избежать несовместимых изменений ваших типов.

Возьмем, к примеру, SystemBObject. Вы описываете «версию 1» и «версию 2» этого типа, но это совсем не один и тот же тип. Совместимое изменение этого типа включает только Добавление свойств, а не изменение типа каких-либо существующих свойств. Ваше гипотетическое «обновление версии» нарушило оба этих ограничения.

Следуя этому единственному правилу, вы можете избежать ВСЕХ проблем, которые вы описали.

Следовательно, если это определение вашего типа в версии 1

class SystemBObject{  // version 1
    String key;  
    Integer year;  
    Integer month;  
    Integer day;  

    ... // getters and setters etc;  
}  

Тогда это не может быть определение вашего типа в версии 2:

// version 2 - NO NO NO 
class SystemBObject{ 
    String key; 
    BDate date; 
    ... // getters and setters etc; 
} 

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

Другой пример: Если это ваш существующий тип v1:

class SomethingFromARequest {   
    Integer requestedId;   
    ... // getters and setters etc;      
}   

... тогда это недопустимый "v2" этого типа:

class SomethingFromARequest {   
    Long requestedId;   
    ... // getters and setters etc;      
}   

... потому что вы изменили тип существующего свойства.

Эти ограничения более подробно объясняются в основном технологически нейтральным способом в статье Microsoft Service Versioning .


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

Кроме того, вы можете разработать прямую совместимость с вашими объектами передачи данных, используя слабую обработку и отображая «лишние» данные в «дополнительное» поле. Если XML является вашим форматом сериализации, вы можете использовать xsd: xmlAny или xsd: any и processContents = "lax" для захвата любых нераспознанных элементов схемы, когда служба v1 получает запрос v2 ( подробнее ). Если ваш формат сериализации - JSON с его более открытой моделью содержимого, то это предоставляется бесплатно.

4
ответ дан 30 November 2019 в 03:52
поделиться

Я знаю, что это поздно для игры, но я достаточно глубоко вник в эту проблему. Я действительно думаю, что лучший ответ включает в себя еще один кусок головоломки: сервисный посредник. Microsoft Managed Services Engine является примером одного - я уверен, что существуют и другие. По сути, изменяя пространство имен XML вашего веб-сервиса (чтобы включить номер версии или дату, как упоминается в связанной статье), вы предоставляете посреднику возможность направлять различные клиентские вызовы к соответствующим реализациям сервера. Дополнительная (и, IMHO, очень крутая) функция MSE - это возможность выполнять преобразование на основе политик. Вы можете определить преобразования XSLT, которые преобразуют запросы v1 в запросы v2 и ответы v2 в ответы v1, что позволяет отказаться от реализации служб v1 без нарушения клиентских реализаций.

3
ответ дан 30 November 2019 в 03:52
поделиться

Я думаю, что еще нужно иметь в виду вашу клиентскую базу, публикуете ли вы эту услугу публично или она ограничена набором известных агентов?

Я участвую в последней ситуации, и мы обнаружил, что решить эту проблему с помощью простого общения / участия не так уж и сложно.

Хотя это только косвенно связано с вашим вопросом, мы обнаружили, что основание нашего номера версии на совместимости, похоже, работает достаточно хорошо. На примере ABC ...

  • A: Изменения, требующие перекомпиляции (нарушающие обратную совместимость)
  • B: Изменения, которые не требуют перекомпиляции, но имеют дополнительные функции, недоступные без этого (новые операции и т. Д.)
  • C: Изменения в базовой механике, которые не изменяют WSDL
3
ответ дан 30 November 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: