Verze služby

Po počátečním nasazení a potenciálně několikrát během jejich životnosti může být potřeba změnit služby (a koncové body, které zpřístupňují) z různých důvodů, jako je změna obchodních potřeb, požadavky na informační technologie nebo řešení jiných problémů. Každá změna zavádí novou verzi služby. Toto téma vysvětluje, jak zvážit správu verzí ve Windows Communication Foundation (WCF).

Čtyři kategorie změn služeb

Změny služeb, které mohou být požadovány, je možné rozdělit do čtyř kategorií:

  • Změny kontraktu: Například může být přidána operace nebo datový prvek ve zprávě může být přidán nebo změněn.

  • Změny adresy: Služba se například přesune do jiného umístění, kde mají koncové body nové adresy.

  • Změny vazby: Například se změní mechanismus zabezpečení nebo se změní jeho nastavení.

  • Změny implementace: Například když se změní implementace interní metody.

Některé z těchto změn se nazývají "rozbíjející" a jiné jsou "nefunkční". Změna se neprobíná , pokud se všechny zprávy, které by byly úspěšně zpracovány v předchozí verzi, úspěšně zpracovávají v nové verzi. Jakákoli změna, která nesplňuje toto kritérium , je zásadní změnou.

Orientace služby a správa verzí

Jednou z principů orientace služeb je, že služby a klienti jsou autonomní (nebo nezávislí). Mimo jiné to znamená, že vývojáři služeb nemohou předpokládat, že řídí nebo dokonce znají všechny klienty služeb. Tím se eliminuje možnost opětovného sestavení a opětovného nasazení všech klientů při změně verzí služby. Toto téma předpokládá, že služba dodržuje tuto sadu, a proto musí být změněna nebo "verze" nezávislá na svých klientech.

V případech, kdy je změna způsobující chybu neočekávaná a nelze se vyhnout, může se aplikace rozhodnout tuto sadu ignorovat a vyžadovat opětovné sestavení a opětovné nasazení klientů s novou verzí služby.

Správa verzí kontraktů

Smlouvy používané klientem nemusí být stejné jako kontrakt používaný službou; musí být kompatibilní pouze.

U kontraktů služeb kompatibilita znamená, že je možné přidat nové operace vystavené službou, ale stávající operace nelze odebrat ani změnit sémanticky.

U kontraktů dat kompatibilita znamená, že je možné přidat nové definice typu schématu, ale existující definice typu schématu nelze měnit zásadními způsoby. Zásadní změny můžou zahrnovat odebrání datových členů nebo změnu jejich datového typu nekompatibilně. Tato funkce umožňuje službě určitou zeměpisnou šířku při změně verze svých kontraktů bez přerušení klientů. Následující dvě části popisují nefunkční a zásadní změny, které je možné provést u dat WCF a kontraktů služeb.

Správa verzí kontraktů dat

Tato část se zabývá správou verzí dat při použití a DataContractSerializerDataContractAttribute tříd.

Striktní správa verzí

V mnoha scénářích při změně verzí je problém, vývojář služby nemá kontrolu nad klienty, a proto nemůže předpokládat, jak by reagovali na změny ve zprávě XML nebo schématu. V těchto případech musíte zaručit, že se nové zprávy ověří ve starém schématu ze dvou důvodů:

  • Staří klienti byli vyvinuti s předpokladem, že se schéma nezmění. Nemusí selhat zpracovat zprávy, pro které nebyly nikdy navrženy.

  • Starší klienti mohou před pokusem o zpracování zpráv provést skutečné ověření schématu proti původnímu schématu.

Doporučeným přístupem v takových scénářích je zacházet s existujícími kontrakty dat jako s neměnnými a vytvářet nové s jedinečnými názvy XML. Vývojář služby pak buď přidá nové metody do existujícího kontraktu služby, nebo vytvoří nový kontrakt služby s metodami, které používají nový datový kontrakt.

Často se stává, že vývojář služby potřebuje napsat určitou obchodní logiku, která by měla běžet ve všech verzích kontraktu dat a obchodní kód specifický pro verzi pro každou verzi kontraktu dat. Příloha na konci tohoto tématu vysvětluje, jak lze rozhraní použít k uspokojení této potřeby.

Lax Versioning

V mnoha dalších scénářích může vývojář služby předpokládat, že přidání nového volitelného člena do datového kontraktu neporuší stávající klienty. To vyžaduje, aby vývojář služby prozkoumal, jestli existující klienti neprovádí ověřování schématu a že ignorují neznámé datové členy. V těchto scénářích je možné využít funkce kontraktů dat k přidání nových členů způsobem, který se nerozbitně. Vývojář služby může tento předpoklad s jistotou provést, pokud se funkce kontraktu dat pro správu verzí už používaly pro první verzi služby.

WCF, ASP.NET webové služby a mnoho dalších zásobníků webových služeb podporují laxní správu verzí: to znamená, že nevyvolají výjimky pro nové neznámé členy dat v přijatých datech.

Je snadné se omylem domnívat, že přidání nového člena neporuší stávající klienty. Pokud si nejste jistí, že všichni klienti můžou zvládnout laxní správu verzí, doporučujeme použít přísné pokyny pro správu verzí a považovat datové kontrakty za neměnné.

Podrobné pokyny pro laxní i striktní správu verzí datových kontraktů najdete v tématu Osvědčené postupy: Správa verzí kontraktů dat.

Rozlišování mezi kontraktem dat a typy .NET

Třídu nebo strukturu .NET lze projektovat jako datový kontrakt použitím DataContractAttribute atributu na třídu. Typ .NET a projekce kontraktů dat jsou dvě různé věci. Je možné mít více typů .NET se stejnou projekcí kontraktu dat. Toto rozlišení je zvlášť užitečné, když vám umožní změnit typ .NET při zachování předpokládaného datového kontraktu, čímž se zachová kompatibilita se stávajícími klienty i v přísném smyslu slova. Pokud chcete zachovat tento rozdíl mezi typem .NET a datovým kontraktem, měli byste vždy provést dvě věci:

  • Zadejte a NameNamespace. Vždy byste měli zadat název a obor názvů vašeho datového kontraktu, aby se zabránilo zveřejnění názvu a oboru názvů vašeho typu .NET v kontraktu. Pokud se později rozhodnete změnit obor názvů nebo typ rozhraní .NET, zůstane kontrakt dat stejný.

  • Zadejte Name. Vždy byste měli zadat název datových členů, aby se zabránilo zveřejnění názvu člena .NET ve smlouvě. Pokud se později rozhodnete změnit název .NET člena, zůstane váš datový kontrakt stejný.

Změna nebo odebrání členů

Změna názvu nebo datového typu člena nebo odebrání datových členů je zásadní změnou, i když je povolená laxní správa verzí. V případě potřeby vytvořte nový kontrakt dat.

Pokud je kompatibilita služeb velmi důležitá, můžete zvážit ignorování nepoužívaných datových členů v kódu a ponechat je na místě. Pokud rozdělujete datový člen na více členů, můžete zvážit, že stávající člen zůstane na místě jako vlastnost, která může provést požadované rozdělení a opětovnou agregaci pro klienty nižší úrovně (klienti, kteří nejsou upgradovány na nejnovější verzi).

Podobně se změny názvu nebo oboru názvů datového kontraktu mění v zásadních změnách.

Odezvy neznámých dat

V některých scénářích je potřeba "round-trip" neznámá data, která pocházejí od členů přidaných do nové verze. Například služba versionNew odesílá data s některými nově přidanými členy do klienta versionOld. Klient při zpracování zprávy ignoruje nově přidané členy, ale znovu odešle stejná data, včetně nově přidaných členů, zpět do služby versionNew. Typickým scénářem je aktualizace dat, kdy se data načítají ze služby, mění a vrací.

Chcete-li povolit odezvu pro určitý typ, musí typ implementovat IExtensibleDataObject rozhraní. Rozhraní obsahuje jednu vlastnost, ExtensionData která vrací ExtensionDataObject typ. Tato vlastnost slouží k ukládání všech dat z budoucích verzí kontraktu dat, která nejsou pro aktuální verzi známa. Tato data jsou neprůhlená pro klienta, ale když je instance serializována, obsah ExtensionData vlastnosti se zapíše se zbytkem dat členů datové smlouvy.

Doporučujeme, aby všechny vaše typy implementovaly toto rozhraní tak, aby vyhovovaly novým a neznámým budoucím členům.

Knihovny kontraktů dat

Mohou existovat knihovny datových kontraktů, ve kterých je kontrakt publikovaný v centrálním úložišti, a implementátory služeb a typů implementují a zveřejňují datové kontrakty z tohoto úložiště. V takovém případě, když publikujete kontrakt dat do úložiště, nemáte žádnou kontrolu nad tím, kdo vytváří typy, které ho implementují. Proto po publikování nelze kontrakt upravit a efektivně ho vykreslovat jako neměnný.

Při použití XmlSerializer

Stejné principy správy verzí platí při použití XmlSerializer třídy. Pokud je vyžadována striktní správa verzí, zacházet s datovými kontrakty jako neměnnými a vytvářet nové datové kontrakty s jedinečnými kvalifikovanými názvy pro nové verze. Pokud jste si jisti, že lze používat laxní správu verzí, můžete přidat nové serializovatelné členy v nových verzích, ale ne změnit nebo odebrat existující členy.

Poznámka:

Pomocí XmlSerializerXmlAnyElementAttribute atributů a XmlAnyAttributeAttribute atributů podporuje zaokrouhlování neznámých dat.

Správa verzí kontraktů zpráv

Pokyny pro správu verzí kontraktů zpráv jsou velmi podobné verzím datových kontraktů. Pokud je vyžadována striktní správa verzí, neměli byste měnit text zprávy, ale místo toho vytvořte nový kontrakt zprávy s jedinečným kvalifikovaným názvem. Pokud víte, že můžete používat laxní správu verzí, můžete přidat nové části textu zprávy, ale ne změnit nebo odebrat stávající. Tyto pokyny platí jak pro holé, tak zabalené kontrakty zpráv.

Záhlaví zpráv je možné vždy přidat, i když se používá striktní správa verzí. Příznak MustUnderstand může mít vliv na správu verzí. Obecně platí, že model správy verzí pro hlavičky ve WCF je popsaný ve specifikaci PROTOKOLU SOAP.

Správa verzí kontraktů služeb

Podobně jako správa verzí kontraktů dat zahrnuje správa verzí kontraktů služeb také operace přidávání, změn a odebírání.

Zadání názvu, oboru názvů a akce

Ve výchozím nastavení je název kontraktu služby název rozhraní. Jeho výchozí obor názvů je http://tempuri.orga každá operace je http://tempuri.org/contractname/methodnameakce . Doporučujeme explicitně zadat název a obor názvů pro kontrakt služby a akci pro každou operaci, aby se zabránilo použití http://tempuri.org a zabránění zveřejnění názvů rozhraní a metod ve smlouvě služby.

Přidání parametrů a operací

Přidání operací služby vystavených službou je neprolomná změna, protože stávající klienti se nemusí zabývat těmito novými operacemi.

Poznámka:

Přidání operací do duplexního kontraktu zpětného volání je zásadní změnou.

Změna parametru operace nebo návratových typů

Změna parametrů nebo návratových typů je obecně zásadní změnou, pokud nový typ neimplementuje stejný datový kontrakt implementovaný starým typem. Pokud chcete takovou změnu provést, přidejte do kontraktu služby novou operaci nebo definujte nový kontrakt služby.

Odebrání operací

Odebráním operací je také zásadní změna. Pokud chcete takovou změnu provést, definujte nový kontrakt služby a zpřístupňte ho na novém koncovém bodu.

Kontrakty chyb

Atribut FaultContractAttribute umožňuje vývojáři kontraktů služeb zadat informace o chybách, které lze vrátit z operací kontraktu.

Seznam chyb popsaných ve smlouvě služby se nepovažuje za vyčerpávající. Kdykoli může operace vrátit chyby, které nejsou popsány ve smlouvě. Změna sady chyb popsaných ve smlouvě se proto nepovažuje za chybu. Například přidání nové chyby do kontraktu pomocí FaultContractAttribute nebo odebrání existující chyby ze smlouvy.

Knihovny kontraktů služeb

Organizace můžou mít knihovny kontraktů, ve kterých se kontrakt publikuje do centrálního úložiště a implementátorů služeb implementují kontrakty z tohoto úložiště. V takovém případě, když publikujete kontrakt služby do úložiště, nemáte žádnou kontrolu nad tím, kdo vytváří služby, které ho implementují. Proto nemůžete po publikování upravit kontrakt služby a efektivně ho tak neměnně vykreslovat. WCF podporuje dědičnost kontraktů, kterou lze použít k vytvoření nového kontraktu, který rozšiřuje stávající kontrakty. Chcete-li použít tuto funkci, definujte nové rozhraní kontraktu služby, které dědí ze starého rozhraní kontraktu služby, a pak přidejte metody do nového rozhraní. Pak změníte službu, která implementuje starý kontrakt tak, aby implementovaly nový kontrakt, a změňte definici koncového bodu versionOld tak, aby používala nový kontrakt. Na klienty versionOld se koncový bod bude dál zobrazovat jako zveřejnění kontraktu versionOld; na klienty versionNew se zobrazí koncový bod, aby zpřístupnil kontrakt versionNew.

Správa verzí adres a vazeb

Změny adresy koncového bodu a vazby jsou zásadními změnami, pokud klienti nebudou schopni dynamicky zjišťovat novou adresu koncového bodu nebo vazbu. Jedním z mechanismů pro implementaci této funkce je použití registru UDDI (Universal Discovery Description and Integration) a modelu volání UDDI, kde se klient pokusí komunikovat s koncovým bodem a při selhání se dotazuje na dobře známý registr UDDI pro aktuální metadata koncového bodu. Klient pak použije adresu a vazbu z těchto metadat ke komunikaci s koncovým bodem. Pokud bude tato komunikace úspěšná, klient do mezipaměti ukládá adresu a informace o vazbě pro budoucí použití.

Směrování služby a správy verzí

Pokud jsou změny provedené ve službě zásadními změnami a potřebujete mít dvě nebo více různých verzí služby spuštěné současně, můžete pomocí služby SMĚROVÁNÍ WCF směrovat zprávy do příslušné instance služby. Služba směrování WCF používá směrování založené na obsahu, jinými slovy, používá informace ve zprávě k určení, kam se má zpráva směrovat. Další informace o službě směrování WCF naleznete v tématu Směrovací služba. Příklad použití služby WCF Routing Service pro správu verzí služby naleznete v tématu Postupy: Správa verzí služby.

Dodatek

Obecné pokyny ke správě verzí kontraktů dat v případě, že je potřeba striktní správa verzí, je zacházet s kontrakty dat jako neměnnými a vytvářet nové, pokud jsou potřeba změny. Pro každý nový kontrakt dat je potřeba vytvořit novou třídu, takže je potřeba mechanismus, aby nemusel přebírat existující kód napsaný z hlediska staré třídy kontraktu dat a přepsat ho z hlediska nové třídy kontraktu dat.

Jedním z těchto mechanismů je použití rozhraní k definování členů každého datového kontraktu a zápisu interního implementačního kódu z hlediska rozhraní, nikoli tříd kontraktů dat, které implementují rozhraní. Následující kód pro verzi 1 služby zobrazuje IPurchaseOrderV1 rozhraní a PurchaseOrderV1:

public interface IPurchaseOrderV1  
{  
    string OrderId { get; set; }  
    string CustomerId { get; set; }  
}  
  
[DataContract(  
Name = "PurchaseOrder",  
Namespace = "http://examples.microsoft.com/WCF/2005/10/PurchaseOrder")]  
public class PurchaseOrderV1 : IPurchaseOrderV1  
{  
    [DataMember(...)]  
    public string OrderId {...}  
    [DataMember(...)]  
    public string CustomerId {...}  
}  

Zatímco operace kontraktu služby by byly napsány z hlediska PurchaseOrderV1, skutečná obchodní logika by byla z hlediska IPurchaseOrderV1. Ve verzi 2 by pak existovalo nové IPurchaseOrderV2 rozhraní a nová PurchaseOrderV2 třída, jak je znázorněno v následujícím kódu:

public interface IPurchaseOrderV2  
{  
    DateTime OrderDate { get; set; }  
}

[DataContract(
Name = "PurchaseOrder",  
Namespace = "http://examples.microsoft.com/WCF/2006/02/PurchaseOrder")]  
public class PurchaseOrderV2 : IPurchaseOrderV1, IPurchaseOrderV2  
{  
    [DataMember(...)]  
    public string OrderId {...}  
    [DataMember(...)]  
    public string CustomerId {...}  
    [DataMember(...)]  
    public DateTime OrderDate { ... }  
}  

Smlouva o poskytování služeb by byla aktualizována tak, aby zahrnovala nové operace napsané z hlediska PurchaseOrderV2. Stávající obchodní logika napsaná z hlediska IPurchaseOrderV1 by nadále fungovala pro PurchaseOrderV2 novou obchodní logiku, která potřebuje OrderDate , by byla napsána z hlediska IPurchaseOrderV2.

Viz také