2016-08-22 6 views
2

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

Предположим, что приведенный ниже сократительный договор для Сводного объекта, и существует API, который получает и обновляет сводку с использованием переданного итогового объекта.

Версия - 1,0

struct Summary { 
    1: required string summaryId, 
    2: required i32 summaryCost 
} 

Summary getSummary(1: string summaryId); 

void updateSummary(1: Summary summary); 

Теперь, скажем, есть 5 услуг, которые используют этот 1,0 договор Резюме.
В следующем выпуске мы добавляем еще один объект, называемый список суммарных значений.

Так что новый контракт будет выглядеть

Версия - 2,0

struct Summary { 
    1: required string summaryId, 
    2: required i32 summaryCost, 
    3: optional list<i32> summaryValues 
} 

Summary getSummary(1: string summaryId); 

void updateSummary(1: Summary summary); 
  1. Так что, когда это ниже список заполняется, мы сохраняем список значений summaryValues aganist этого summaryId.
  2. И когда клиент отправляет этот список как null, мы удаляем существующие значения, сохраненные для этого «summaryId».

Теперь проблема возникает, когда другие услуги, которые используют СТАРШЕ версию контракта бережливость (Version 1.0) попытаться вызвать getSummary и updateSummary.
Целью Старого клиента путем вызова updateSummary было установить другое значение для summaryCost. Однако, поскольку этот клиент не содержит объект summaryValues, он отправляет объект Summary с summaryValues как null на сервер.

В результате Сервер удаляет все существующие значения summaryValues за это summaryId.

Есть ли способ справиться с этим в бережливости? Методы isSet() здесь не работают, поскольку они пытаются выполнить простую нулевую проверку.
Каждый раз, когда мы выпускаем нового клиента с модификацией существующих объектов, нам приходится принудительно обновлять клиентские версии других серверов, даже если изменение не связано с ними.

ответ

1

В вашем version 2.0 контракт метода updateSummary() изменился (то есть, теперь она позволяет сохранять и удалять суммарные значения):

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

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


Вариант 2: Добавить дополнительное поле, которое содержит версию апи и имеет значение по умолчанию, установленное для последней версии API:

struct Summary { 
    1: required string summaryId, 
    2: required i32 summaryCost, 
    3: optional list<i32> summaryValues 
    4: optional i32 apiVersion = 2 
} 

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


В качестве альтернативы, можно только удалить записи, если пустой список при условии, и ничего не делать, если список не задан, уважать предыдущий контракт метода.

В качестве побочного примечания: наличие действия зависит от чего-то неявного (здесь, отсутствия списка), может быть рискованным вообще, даже без учета проблемы совместимости. Обычно это безопаснее (и проще работать и обслуживать), когда такие действия зависят от явного флага.

+0

Создание другого API сделает обслуживание кода очень громоздким, потому что нам нужно помнить, какая функция была добавлена ​​как часть API. Все может легко выйти из-под контроля. Кроме того, наличие emptylist может оказаться невозможным, так как мы должны сообщать обо всех зависимых клиентах, чтобы добавить это поведение, даже если они не заинтересованы в этом поле. –

+0

«нам нужно запомнить, какая функция была добавлена ​​как часть API» -> Это похоже на то, что вам, вероятно, придется делать в контексте API с несколькими версиями :). Я обновил ответ с помощью другого варианта. – Shastick

+0

@BandiKishore -> любая обратная связь по второму варианту? :) – Shastick