Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A készletezési minta bemutatja, hogyan terjeszthető ki a Windows Communication Foundation (WCF) az objektumkészletezés támogatására. A minta bemutatja, hogyan hozhat létre olyan attribútumot, amely szintaktikailag és szemantikailag hasonló az ObjectPoolingAttribute Enterprise Services attribútumfunkcióihoz. Az objektumkészletezés jelentősen növelheti az alkalmazások teljesítményét. Azonban ennek ellenkező hatása lehet, ha nem megfelelően használják. Az objektumkészletezés segít csökkenteni a gyakran használt, nagy inicializálást igénylő objektumok újrajavításának többletterhelését. Ha azonban egy készletezett objektum metódusának hívása jelentős időt vesz igénybe, az objektumkészletezés további kéréseket küld, amint eléri a készlet maximális méretét. Így előfordulhat, hogy egy időtúllépési kivétel kivetésével nem sikerül kiszolgálni néhány objektumlétrehozási kérést.
Megjegyzés:
A minta telepítési eljárása és összeállítási utasításai a témakör végén találhatók.
A WCF-bővítmények létrehozásának első lépése a bővíthetőségi pont kiválasztása.
A WCF-ben a diszpécser kifejezés egy futtatókörnyezeti összetevőre utal, amely felelős a bejövő üzenetek metódushívásokká alakításáért a felhasználó szolgáltatásában, valamint a visszatérési értékeknek a metódusból kimenő üzenetté alakításáért. A WCF-szolgáltatás minden végponthoz létrehoz egy diszpécsert. A WCF-ügyfélnek diszpécser szolgáltatást kell használnia, ha az ügyfélhez társított szerződés duplex szerződés.
A csatorna- és végpont-diszpécserek csatorna- és szerződésszintű bővíthetőséget kínálnak a diszpécser viselkedését szabályozó különböző tulajdonságok felfedésével. A DispatchRuntime tulajdonság lehetővé teszi a küldési folyamat vizsgálatát, módosítását vagy testreszabását is. Ez a minta a InstanceProvider szolgáltatásosztály példányait biztosító objektumra mutató tulajdonságra összpontosít.
Az IInstanceProvider
A WCF-ben a diszpécser létrehozza a szolgáltatásosztály példányait egy InstanceProvider használatával, amely az IInstanceProvider interfészt implementálja. Ennek a felületnek három módszere van:
GetInstance(InstanceContext, Message): Amikor egy üzenet megérkezik, a diszpécser meghívja a metódust, GetInstance(InstanceContext, Message) hogy hozzon létre egy példányt a szolgáltatásosztályból az üzenet feldolgozásához. A metódus hívásainak gyakoriságát a InstanceContextMode tulajdonság határozza meg. Ha például a InstanceContextMode tulajdonság úgy van beállítva, hogy egy új példány jön létre a szolgáltatásosztályból minden beérkező üzenet feldolgozására, akkor PerCall meghívódik minden egyes üzenet érkezésekor.
GetInstance(InstanceContext): Ez megegyezik az előző módszerrel, kivéve, ha nincs üzenetargumentum.
ReleaseInstance(InstanceContext, Object): Amikor egy szolgáltatáspéldány élettartama lejárt, a diszpécser meghívja a metódust ReleaseInstance(InstanceContext, Object) . A metódushoz GetInstance(InstanceContext, Message) hasonlóan a metódus hívásainak gyakoriságát is a InstanceContextMode tulajdonság határozza meg.
Az objektumkészlet
Az egyéni IInstanceProvider implementáció biztosítja a szolgáltatáshoz szükséges objektumkészletezési szemantikát. Ezért ez a minta olyan típussal ObjectPoolingInstanceProvider rendelkezik, amely egyéni implementációt biztosít a IInstanceProvider készletezéshez. Amikor a Dispatcher metódus meghívja a GetInstance(InstanceContext, Message) metódust, ahelyett, hogy új példányt hoz létre, az egyéni implementáció egy meglévő objektumot keres a memóriában lévő készletben. Ha elérhető, a függvény visszaadja. Ellenkező esetben létrejön egy új objektum. A megvalósítás a GetInstance következő mintakódban látható.
object IInstanceProvider.GetInstance(InstanceContext instanceContext, Message message)
{
object obj = null;
lock (poolLock)
{
if (pool.Count > 0)
{
obj = pool.Pop();
}
else
{
obj = CreateNewPoolObject();
}
activeObjectsCount++;
}
WritePoolMessage(ResourceHelper.GetString("MsgNewObject"));
idleTimer.Stop();
return obj;
}
Az egyéni ReleaseInstance implementáció hozzáadja a felszabadított példányt a készlethez, és lecsökkenti az ActiveObjectsCount értéket. Ezek Dispatcher a metódusok különböző szálakból hívhatók meg, ezért szinkronizált hozzáférésre van szükség az ObjectPoolingInstanceProvider osztály osztályszintű tagjaihoz.
void IInstanceProvider.ReleaseInstance(InstanceContext instanceContext, object instance)
{
lock (poolLock)
{
pool.Push(instance);
activeObjectsCount--;
WritePoolMessage(
ResourceHelper.GetString("MsgObjectPooled"));
// When the service goes completely idle (no requests
// are being processed), the idle timer is started
if (activeObjectsCount == 0)
idleTimer.Start();
}
}
A ReleaseInstance metódus "tisztítási inicializálás" funkciót biztosít. A készlet általában minimális számú objektumot tart fenn a készlet élettartamára vonatkozóan. Előfordulhat azonban, hogy a túlzott használat miatt további objektumokat kell létrehozni a készletben, hogy elérjék a konfigurációban megadott maximális korlátot. Végül, amikor a medence kevésbé aktívvá válik, ezek a felesleges objektumok többletterhet jelenthetnek. Ezért amikor a activeObjectsCount nullát eléri, elindul egy tétlen időzítő, amely elindítja és elvégzi a tisztítási ciklust.
A viselkedés hozzáadása
A diszpécserréteg bővítményei a következő viselkedéssel vannak összekapcsolva:
Szolgáltatás viselkedése. Ezek lehetővé teszik a teljes szolgáltatás-futtatókörnyezet testreszabását.
Végpont viselkedése. Ezek lehetővé teszik a szolgáltatásvégpontok, különösen a csatorna- és végpont-diszpécser testreszabását.
Szerződési viselkedések. Ezek lehetővé teszik az ügyfél és a szolgáltatás mindkét ClientRuntime és DispatchRuntime osztályának testreszabását.
Az objektumkészletezési bővítmény céljából létre kell hozni egy szolgáltatás viselkedését. A szolgáltatás viselkedése a IServiceBehavior felület implementálásával jön létre. Számos mód van arra, hogy a szolgáltatásmodell tudatára ébredjen az egyéni viselkedéseknek.
Egyéni attribútum használata.
Feltétlenül adja hozzá a szolgáltatásleírás viselkedésgyűjteményéhez.
A konfigurációs fájl kiterjesztése.
Ez a minta egy egyéni attribútumot használ. A ServiceHost felépítéskor megvizsgálja a szolgáltatás típusdefiníciójában használt attribútumokat, és hozzáadja az elérhető viselkedéseket a szolgáltatásleírás viselkedésgyűjteményéhez.
Az interfészben IServiceBehavior három metódus található : Validate, AddBindingParametersés ApplyDispatchBehavior. Ezzel Validate a módszerrel biztosítható, hogy a viselkedés alkalmazható legyen a szolgáltatásra. Ebben a példában az implementáció biztosítja, hogy a szolgáltatás Single nélkül legyen konfigurálva. A AddBindingParameters metódus a szolgáltatás kötéseinek konfigurálására szolgál. Ebben a forgatókönyvben ez nem kötelező. Ez ApplyDispatchBehavior a szolgáltatás diszpécsereinek konfigurálására szolgál. Ezt a metódust a WCF hívja meg az ServiceHost inicializáláskor. A rendszer a következő paramétereket adja át a metódusnak:
Description: Ez az argumentum a teljes szolgáltatás szolgáltatásleírását tartalmazza. Ez a szolgáltatás végpontjaival, szerződésekkel, kötésekkel és egyéb adatokkal kapcsolatos leírási adatok vizsgálatára használható.ServiceHostBase: Ez az argumentum a ServiceHostBase jelenleg inicializálandó argumentumot adja meg.
Az egyéni IServiceBehavior implementációban a ServiceHostBase mindegyikében a rendszer létrehoz egy új ObjectPoolingInstanceProvider példányt, amelyet a InstanceProvider tulajdonsághoz rendel a DispatchRuntime elemben.
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
// Create an instance of the ObjectPoolInstanceProvider.
ObjectPoolingInstanceProvider instanceProvider = new
ObjectPoolingInstanceProvider(description.ServiceType,
minPoolSize);
// Forward the call if we created a ServiceThrottlingBehavior.
if (this.throttlingBehavior != null)
{
((IServiceBehavior)this.throttlingBehavior).ApplyDispatchBehavior(description, serviceHostBase);
}
// In case there was already a ServiceThrottlingBehavior
// (this.throttlingBehavior==null), it should have initialized
// a single ServiceThrottle on all ChannelDispatchers.
// As we loop through the ChannelDispatchers, we verify that
// and modify the ServiceThrottle to guard MaxPoolSize.
ServiceThrottle throttle = null;
foreach (ChannelDispatcherBase cdb in
serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
// Make sure there is exactly one throttle used by all
// endpoints. If there were others, we could not enforce
// MaxPoolSize.
if ((this.throttlingBehavior == null) &&
(this.maxPoolSize != Int32.MaxValue))
{
throttle ??= cd.ServiceThrottle;
if (cd.ServiceThrottle == null)
{
throw new
InvalidOperationException(ResourceHelper.GetString("ExNullThrottle"));
}
if (throttle != cd.ServiceThrottle)
{
throw new InvalidOperationException(ResourceHelper.GetString("ExDifferentThrottle"));
}
}
foreach (EndpointDispatcher ed in cd.Endpoints)
{
// Assign it to DispatchBehavior in each endpoint.
ed.DispatchRuntime.InstanceProvider =
instanceProvider;
}
}
}
// Set the MaxConcurrentInstances to limit the number of items
// that will ever be requested from the pool.
if ((throttle != null) && (throttle.MaxConcurrentInstances >
this.maxPoolSize))
{
throttle.MaxConcurrentInstances = this.maxPoolSize;
}
}
A megvalósítás mellett IServiceBehavior az ObjectPoolingAttribute osztály több taggal is rendelkezik az objektumkészlet testreszabásához az attribútumargumentumok használatával. Ezek a tagok a .NET Enterprise Services által biztosított objektumkészletezési funkciókészletnek megfelelőt tartalmazzákMaxPoolSizeMinPoolSizeCreationTimeout.
Az objektumkészletezési viselkedés mostantól hozzáadható egy WCF-szolgáltatáshoz a szolgáltatás implementációjának megjegyzésével az újonnan létrehozott egyéni ObjectPooling attribútummal.
[ObjectPooling(MaxPoolSize=1024, MinPoolSize=10, CreationTimeout=30000)]
public class PoolService : IPoolService
{
// …
}
Minta tesztelése
A minta bemutatja azokat a teljesítménybeli előnyöket, amelyek bizonyos helyzetekben az objektumkészletezés használatával nyerhetők.
A szolgáltatásalkalmazás két szolgáltatást valósít meg – WorkService és ObjectPooledWorkService. Mindkét szolgáltatás ugyanazzal a megvalósítással rendelkezik – mindkettő költséges inicializálást igényel, majd egy DoWork() viszonylag olcsó módszert tesz elérhetővé. Az egyetlen különbség az, hogy az ObjectPooledWorkService objektumkészletezés konfigurálva van:
[ObjectPooling(MinPoolSize = 0, MaxPoolSize = 5)]
public class ObjectPooledWorkService : IDoWork
{
public ObjectPooledWorkService()
{
Thread.Sleep(5000);
ColorConsole.WriteLine(ConsoleColor.Blue, "ObjectPooledWorkService instance created.");
}
public void DoWork()
{
ColorConsole.WriteLine(ConsoleColor.Blue, "ObjectPooledWorkService.GetData() completed.");
}
}
A kliens futtatásakor 5 alkalommal méri az WorkService hívását. Ezután időzíti, hogy a ObjectPooledWorkService 5-ször legyen meghívva. Ekkor megjelenik az időkülönbség:
Press <ENTER> to start the client.
Calling WorkService:
1 - DoWork() Done
2 - DoWork() Done
3 - DoWork() Done
4 - DoWork() Done
5 - DoWork() Done
Calling WorkService took: 26722 ms.
Calling ObjectPooledWorkService:
1 - DoWork() Done
2 - DoWork() Done
3 - DoWork() Done
4 - DoWork() Done
5 - DoWork() Done
Calling ObjectPooledWorkService took: 5323 ms.
Press <ENTER> to exit.
Megjegyzés:
Az ügyfél első futtatásakor úgy tűnik, hogy a két szolgáltatás körülbelül ugyanannyi időt vesz igénybe. Ha újra futtatja a mintát, láthatja, hogy a ObjectPooledWorkService sokkal gyorsabban visszatér, mert az objektum egy példánya már létezik a poolban.
A példa beállítása, elkészítése és futtatása
Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták One-Time beállítási eljárását.
A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.
Ha a mintát egy vagy több gép közötti konfigurációban szeretné futtatni, kövesse A Windows Communication Foundation-minták futtatásacímű témakör utasításait.
Megjegyzés:
Ha a Svcutil.exe használatával hozza létre újra a minta konfigurációját, mindenképpen módosítsa az ügyfélkonfiguráció végpontnevét az ügyfélkódnak megfelelően.