Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Inicializační ukázka rozšiřuje ukázku sdružování definováním rozhraní, IObjectControlkteré přizpůsobí inicializaci objektu aktivací a deaktivací. Klient vyvolá metody, které vrací objekt do fondu a které nevracely objekt do fondu.
Poznámka:
Postup nastavení a pokyny k sestavení pro tuto ukázku najdete na konci tohoto tématu.
Body rozšiřitelnosti
Prvním krokem při vytváření rozšíření WCF (Windows Communication Foundation) je rozhodnutí o bodu rozšiřitelnosti, který se má použít. Ve WCF termín EndpointDispatcher odkazuje na komponentu modulu runtime zodpovědnou za převod příchozích zpráv na volání metod ve službě uživatele a k převodu vrácených hodnot z této metody na odchozí zprávu. Pro každý koncový bod vytvoří služba WCF koncový bod EndpointDispatcher.
EndpointDispatcher nabízí rozsah koncového bodu (pro všechny zprávy přijaté nebo odeslané službou) rozšiřitelnost pomocí EndpointDispatcher třídy. Tato třída umožňuje přizpůsobit různé vlastnosti, které řídí chování EndpointDispatcher. Tato ukázka se zaměřuje na InstanceProvider vlastnost, která odkazuje na objekt, který poskytuje instance třídy služby.
IInstanceProvider
Ve wcf EndpointDispatcher vytváří instance třídy služby pomocí zprostředkovatele instance, který implementuje IInstanceProvider rozhraní. Toto rozhraní má pouze dvě metody:
GetInstance: Při příchodu zprávy dispatcher zavolá metodu GetInstance k vytvoření instance třídy služby pro zpracování zprávy. Frekvence volání této metody je určena InstanceContextMode vlastností. Pokud je například vlastnost nastavena InstanceContextMode na InstanceContextMode.PerCall, vytvoří se nová instance třídy služby pro zpracování každé příchozí zprávy, takže GetInstance je volána při příchodu zprávy.
ReleaseInstance: Když instance služby dokončí zpracování zprávy, EndpointDispatcher volá metodu ReleaseInstance . Stejně jako v GetInstance metodě je frekvence volání této metody určena InstanceContextMode vlastností.
Fond objektů
Třída ObjectPoolInstanceProvider obsahuje implementaci fondu objektů. Tato třída implementuje IInstanceProvider rozhraní pro interakci s vrstvou modelu služby. Když EndpointDispatcher volá metodu GetInstance místo vytvoření nové instance, vlastní implementace hledá existující objekt ve fondu v paměti. Pokud je k dispozici, vrátí se. V opačném případě zkontroluje, ObjectPoolInstanceProvider zda ActiveObjectsCount vlastnost (počet objektů vrácených z fondu) dosáhla maximální velikosti fondu. Pokud ne, vytvoří se nová instance a vrátí se volajícímu a ActiveObjectsCount následně se zvýší. V opačném případě se požadavek na vytvoření objektu zařadí do fronty po nakonfigurované časové období. Implementace je GetObjectFromThePool znázorněna v následujícím ukázkovém kódu.
private object GetObjectFromThePool()
{
bool didNotTimeout =
availableCount.WaitOne(creationTimeout, true);
if(didNotTimeout)
{
object obj = null;
lock (poolLock)
{
if (pool.Count != 0)
{
obj = pool.Pop();
activeObjectsCount++;
}
else if (pool.Count == 0)
{
if (activeObjectsCount < maxPoolSize)
{
obj = CreateNewPoolObject();
activeObjectsCount++;
#if (DEBUG)
WritePoolMessage(
ResourceHelper.GetString("MsgNewObject"));
#endif
}
}
idleTimer.Stop();
}
// Call the Activate method if possible.
if (obj is IObjectControl)
{
((IObjectControl)obj).Activate();
}
return obj;
}
throw new TimeoutException(
ResourceHelper.GetString("ExObjectCreationTimeout"));
}
Vlastní ReleaseInstance implementace přidá uvolněnou instanci zpět do fondu a sníží ActiveObjectsCount hodnotu. EndpointDispatcher může volat tyto metody z různých vláken, a proto je vyžadován synchronizovaný přístup k členům úrovně třídy ve ObjectPoolInstanceProvider třídě.
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
lock (poolLock)
{
// Check whether the object can be pooled.
// Call the Deactivate method if possible.
if (instance is IObjectControl)
{
IObjectControl objectControl = (IObjectControl)instance;
objectControl.Deactivate();
if (objectControl.CanBePooled)
{
pool.Push(instance);
#if(DEBUG)
WritePoolMessage(
ResourceHelper.GetString("MsgObjectPooled"));
#endif
}
else
{
#if(DEBUG)
WritePoolMessage(
ResourceHelper.GetString("MsgObjectWasNotPooled"));
#endif
}
}
else
{
pool.Push(instance);
#if(DEBUG)
WritePoolMessage(
ResourceHelper.GetString("MsgObjectPooled"));
#endif
}
activeObjectsCount--;
if (activeObjectsCount == 0)
{
idleTimer.Start();
}
}
availableCount.Release(1);
}
Metoda ReleaseInstance poskytuje funkci inicializace vyčištění. Fond obvykle udržuje minimální počet objektů po dobu životnosti fondu. Může však existovat období nadměrného využití, která vyžadují vytvoření dalších objektů ve fondu, aby dosáhla maximálního limitu zadaného v konfiguraci. Když se fond stane méně aktivními, může se stát, že se tyto nadbytečné objekty stanou nadbytečnou režií. Pokud tedy activeObjectsCount dosáhne nuly, spustí se časovač nečinnosti, který aktivuje a provede cyklus čištění.
if (activeObjectsCount == 0)
{
idleTimer.Start();
}
Rozšíření vrstvy ServiceModel se připojují pomocí následujícího chování:
Chování služby: To umožňuje přizpůsobení celého modulu runtime služby.
Chování koncových bodů: To umožňuje přizpůsobení konkrétního koncového bodu služby, včetně koncového bodu EndpointDispatcher.
Chování kontraktů: To umožňuje přizpůsobení buď ClientRuntime nebo DispatchRuntime tříd v klientovi nebo službě v uvedeném pořadí.
Chování operací: To umožňuje přizpůsobení buď ClientOperation nebo DispatchOperation tříd v klientovi nebo službě.
Pro účely rozšíření sdružování objektů je možné vytvořit chování koncového bodu nebo chování služby. V tomto příkladu používáme chování služby, které používá schopnost sdružování objektů na každý koncový bod služby. Chování služby se vytváří implementací IServiceBehavior rozhraní. ServiceModel o vlastním chování si můžete uvědomit několika způsoby:
Použití vlastního atributu
Imperativním přidáním do kolekce chování popisu služby.
Rozšíření konfiguračního souboru
Tato ukázka používá vlastní atribut. Při ServiceHost vytváření prozkoumá atributy použité v definici typu služby a přidá dostupné chování do kolekce chování popisu služby.
Rozhraní IServiceBehavior má tři metody: Validate,AddBindingParameters, a .ApplyDispatchBehavior Tyto metody jsou volány WCF při ServiceHost inicializaci.
IServiceBehavior.Validate je volána jako první; umožňuje službě kontrolovat nekonzistence.
IServiceBehavior.AddBindingParameters se nazývá další; tato metoda se vyžaduje pouze ve velmi pokročilých scénářích.
IServiceBehavior.ApplyDispatchBehavior je volána jako poslední a zodpovídá za konfiguraci modulu runtime. Do těchto parametrů se předávají IServiceBehavior.ApplyDispatchBehaviornásledující parametry:
Description: Tento parametr poskytuje popis služby pro celou službu. Můžete ho použít ke kontrole popisových dat o koncových bodech, kontraktech, vazbách a dalších datech přidružených ke službě.ServiceHostBase: Tento parametr poskytuje ServiceHostBase právě inicializovaný parametr.
Ve vlastní IServiceBehavior implementaci je nová instance instance ObjectPoolInstanceProvider instance a přiřazena k InstanceProvider vlastnosti v každém EndpointDispatcher , který je připojen k objektu ServiceHostBase.
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
if (enabled)
{
// Create an instance of the ObjectPoolInstanceProvider.
instanceProvider = new ObjectPoolInstanceProvider(description.ServiceType,
maxPoolSize, minPoolSize, creationTimeout);
// Assign our instance provider to Dispatch behavior in each
// endpoint.
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
}
}
Kromě IServiceBehavior implementace ObjectPoolingAttribute třída má několik členů pro přizpůsobení fondu objektů pomocí argumentů atributu. Mezi tyto členy patří MaxSize, MinSizeEnableda CreationTimeout, aby odpovídaly sadě funkcí sdružování objektů poskytované službami .NET Enterprise Services.
Chování při sdružování objektů je teď možné přidat do služby WCF přidáním poznámek k implementaci služby pomocí nově vytvořeného vlastního ObjectPooling atributu.
[ObjectPooling(MaxSize=1024, MinSize=10, CreationTimeout=30000]
public class PoolService : IPoolService
{
// …
}
Aktivace a deaktivace připojení
Primárním cílem sdružování objektů je optimalizovat krátkodobé objekty s relativně nákladným vytvořením a inicializací. Proto může aplikaci v případě správného použití výrazně zvýšit výkon. Vzhledem k tomu, že objekt je vrácen z fondu, je konstruktor volána pouze jednou. Některé aplikace však vyžadují určitou úroveň řízení, aby mohly inicializovat a vyčistit prostředky použité během jednoho kontextu. Například objekt, který se používá pro sadu výpočtů, může před zpracováním dalšího výpočtu resetovat svá soukromá pole. Podnikové služby povolily tento druh inicializace specifické pro konkrétní kontext tím, že umožňují vývojáři objektu přepsat Activate a Deactivate metody ze ServicedComponent základní třídy.
Fond objektů volá metodu Activate těsně před vrácením objektu z fondu.
Deactivate je volána, když se objekt vrátí zpět do fondu. Základní ServicedComponent třída má boolean také vlastnost s názvem CanBePooled, která lze použít k upozorňovat fondu, zda lze objekt dále fondovat.
Pro napodobení této funkce ukázka deklaruje veřejné rozhraní (IObjectControl), které má výše uvedené členy. Toto rozhraní je pak implementováno třídami služeb určenými k poskytnutí kontextové inicializace. Implementace musí být upravena IInstanceProvider tak, aby splňovala tyto požadavky. Teď, když získáte objekt voláním GetInstance metody, musíte zkontrolovat, zda objekt implementuje IObjectControl. If it, musíte metodu Activate odpovídajícím způsobem volat.
if (obj is IObjectControl)
{
((IObjectControl)obj).Activate();
}
Při vrácení objektu do fondu se před přidáním objektu zpět do fondu vyžaduje CanBePooled kontrola vlastnosti.
if (instance is IObjectControl)
{
IObjectControl objectControl = (IObjectControl)instance;
objectControl.Deactivate();
if (objectControl.CanBePooled)
{
pool.Push(instance);
}
}
Vzhledem k tomu, že vývojář služby může rozhodnout, jestli může být objekt ve fondu, může v daném okamžiku jít pod minimální velikost. Proto je nutné zkontrolovat, zda počet objektů byl nižší než minimální úroveň, a provést nezbytné inicializace v postupu vyčištění.
// Remove the surplus objects.
if (pool.Count > minPoolSize)
{
// Clean the surplus objects.
}
else if (pool.Count < minPoolSize)
{
// Reinitialize the missing objects.
while(pool.Count != minPoolSize)
{
pool.Push(CreateNewPoolObject());
}
}
Při spuštění ukázky se požadavky na operace a odpovědi zobrazí v oknech služby i konzoly klienta. Stisknutím klávesy Enter v každém okně konzoly vypnete službu a klienta.
Nastavení, sestavení a spuštění ukázky
Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.
Pokud chcete sestavit řešení, postupujte podle pokynů v části Sestavení ukázek Windows Communication Foundation.
Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.