ASPNL logo (1 kb)
zaterdag 17 mei 2008




Microsoft MVP

.NET Codewise Community
<< vorige | overzicht | volgende >>

.NET: Enterprise Services

Door Michiel van Otegem
8 augustus 2006

Sommige applicaties hebben eisen die net even verder gaan dan wat een normaal ontwikkelplatform biedt. Dit geldt voor applicaties gebaseerd op COM, maar net zo goed voor .NET. Binnen .NET maken we voor die applicaties gebruik van Enterprise Services, beter bekend als COM+ Component Services.

Bij mensen die al enigszins bekend zijn met .NET, moeten er nu allerlei bellen gaan rinkelen. Want .NET heeft toch helemaal niets te maken met COM? Correct, maar COM+ is geen COM. COM+ is eigenlijk een verzameling diensten waar COM gebruik van kan maken. Die diensten zijn zo generiek, dat ze eigenlijk voor elke component technologie wat te bieden hebben, dus ook voor .NET. Waar de naamsverwarring vandaan komt kun je lezen in het kader "De geschiedenis van COM+ Component Services".
De diensten die COM+ Components Services (verder in dit artikel genoemd COM+) biedt zijn allemaal bedoeld om het leven van ontwikkelaars en beheerders makkelijker te maken. Een van de meest in het oog springende diensten is transactie management. Je kunt een component zo maken dat het deel kan nemen in een COM+ transactie. Binnen een transactie wordt gezorgd dat alle operaties die door verschillende componenten uitgevoerd worden allemaal goed gaan, of allemaal niet uitgevoerd worden. Door gebruik te maken van COM+, is hiervoor nauwelijks extra code nodig, omdat COM+ het op zich neemt alle componenten te melden of de transactie gelukt is of niet. Maakt je component gebruik van bijvoorbeeld SQL Server, dan worden alle gegevens die je gewijzigd hebt toen de transactie nog liep automatisch teruggedraaid. Doet je component iets heel specifieks, dan kan het nodig zijn een functie te bieden die de zaken terugdraait als de transactie faalt, maar verder hoef je je niet druk te maken om alle zaken die met transacties te maken hebben. Doordat zowel COM componenten als .NET componenten gebruik kunnen maken van COM+, is het mogelijk om beide soorten componenten te gebruiken binnen dezelfde transactie. Zo maakt COM+ het dus ook relatief eenvoudig om hybride applicaties te maken.
Een dienst die verwant is aan transactie management is synchronisatie. Veel COM componenten zijn geschreven in Visual Basic, dat het niet toe staat dat meerdere applicaties (of instanties van applicaties) tegelijk een component gebruiken. Doe je dit toch, dan roep je allerlei problemen over je af, die uiteindelijk kunnen leiden tot een crash van je applicatie of zelfs het systeem. COM+ zorgt voor deze componenten dat slechts één applicatie tegelijk gebruik kan maken van een component. Zo kunnen ontwikkelaars blijven programmeren alsof ze voor een enkele gebruiker schrijven, terwijl ze in feite multi-user applicaties kunnen maken. Hier hangt mee samen dat COM+ ook aan object instantie management doet. Dit wil zeggen dat COM+ ervoor zorgt dat er zonodig meerdere kopiëen van een component beschikbaar zijn in een “pool”. Dit wordt daarom ook vaak object pooling genoemd. Wanneer een applicatie een component nodig heeft, wordt dit toegewezen uit de pool. Is het klaar met een component, dan wordt de component niet opgeruimd, maar weer teruggeplaatst in de pool, zodat andere applicaties er gebruik van kunnen maken. Dit heeft als voordeel dat er veel minder overhead is voor het instantiëren van componenten, en bovendien dat niet voor iedere lopende applicatie een kopie van een component nodig is, doordat componenten gedeeld worden tussen applicaties. Het kan echter zijn dat applicaties juist wel hun eigen componenten nodig hebben, en het liefst zo snel mogelijk weer afsluiten. Dit komt bijvoorbeeld voor als een bestand open gehouden wordt door een component. Voor die situatie biedt COM+ een andere techniek, die bekend staat als Just In Time Activation (JITA). JITA zorgt ervoor dat een component dat een applicatie constant in gebruik heeft alleen geactiveerd wordt op het moment dat het echt nodig is, en ook weer vrijgeeft zodra dit kan. JITA is echter alleen interssant voor componenten die een betrekkelijk lage overhead hebben om te creëren, het omgekeerde van waarvoor object pooling bedoeld is dus eigenlijk. Naast de diensten die ervoor zorgen dat je als ontwikkelaar geen omkijken meer hebt naar transactie management en schaalbaarheidsproblemen, biedt COM+ ook nog beveiliging op component niveau. Je kunt een component namelijk zo instellen dat het alleen gebruikt mag worden door bepaalde gebruikers. Verder kun je dat zelfde component zo instellen dat het uitgevoerd wordt onder een bepaalde gebruiker, of zich voor doet als een bepaalde gebruiker. Dit heeft als voordeel dat je beveiligingsbeheer op een centrale plek kunt doen, en dat je toegang kunt geven tot bepaalde functionaliteit via een component, terwijl diezelfde functionaliteit niete direct beschikbaar is. Een database server is daarvan een mooi voorbeeld. Het laatste wat je namelijk wilt doen is veel verschillende gebruikers daar toegang toe geven. Sterker nog, eigenlijk wil je maar zelden dat gebruikers direct gegevens kunnen manipuleren in een database. Dat moet over het algemeen via een applicatie. Door die functionaleit in een component te steken dat werkt onder COM+, kun je toegang geven tot de database aan die component, maar niet aan de afzonderlijke gebruikers. Die gebruikers geef je weer toegang tot de component. Men spreekt ook wel van het delegeren van de beveiliging, omdat de daadwerkelijke toegang overgelaten wordt aan een ander gebruikersaccount.
De laatste twee diensten die COM+ biedt hebben alles te maken met flexibiliteit: queued components en events. Queued components biedt de mogelijkheid om functies asynchroon aan te roepen. In feite wordt een aanroep in een qwachtrij geplaatst, en uitgevoerd zodra dit kan. Dit betekent dat een component niet beschikbaar hoeft te zijn ten tijde van de aanroep. Dit is bijvoorbeeld het geval als je een client applicatie meeneemt naar een omgeving waar geen netwerk beschikbaar is. Bepaalde operaties kun je dan toch uitvoeren, omdat die op een later tijdstip alsnog uitgevoerd worden, zonder dat je daar iets voor hoeft te doen. De events dienst biedt een publisher-subscriber model voor gebeurtenissen. Een component kan zich als het ware inschrijven op gebeurtenissen die een ander component kan veroorzaken. Op het moment dat die gebeurtenis plaatvindt, worden alle subscribers daarvan op de hoogte gesteld, en kan de nodig actie ondernomen worden. COM+ maakt zonodig de objecten die zich ingeschreven hebben voor de gebeurtenis aan.

De geschiedenis van COM+ Component Services
Sinds midden jaren negentig wordt op Windows geprogrammeerd op basis van het Component Object Model (COM). COM componenten bevatten een speciale binaire interface die het mogelijk maakt om gebruik te maken van de functionaliteit in een component, zonder dat bekend is hoe die component intern in elkaar zit. Hierdoor kunnen componenten los van elkaar ontwikkeld worden, en kunnen deze dynamisch aan elkaar gekoppeld worden. Zolang alle componenten zich aan de gedefinieerde interface houden, kan de interne werking daarvan veranderd worden zonder problemen op te leveren in applicaties die gebruik maken van die componenten. Later ontwikkelde Microsoft Distributed COM (DCOM), zodat het mogelijk werd om componenten aan te roepen die op een andere machine uitgevoerd worden. Aan DCOM zitten wel wat haken en ogen. Wat gebeurt er bijvoorbeeld als een andere machine (tijdelijk) down is, en hoe bepaal je of een applicatie die uitgevoerd wordt op een andere machine gebruik mag maken een component? Een ander vraagstuk dat indertijd belangrijk begon te worden was hoe men er voor zorgt dat allerlei operaties die door verschillende componenten uitgevoerd worden als transactie uitgevoerd kunnen worden. Met andere woorden, hoe zorg je ervoor dat alle operaties goed gaan, en dat als er een operatie van meerdere fout gaat, de andere operaties ook niet uitgevoerd (of teruggedraaid) worden. In een poging deze problemen op te lossen werd in 1998 Microsoft Transaction Server (MTS) geïntroduceerd. Hoewel de naam suggereert dat MTS alleen voor transactiemanagement zorgt, maar zoals je kunt lezen in dit artikel doet het veel meer. MTS was een stap in de goede richting, maar door een gebrek aan integratie met het operating systeem en COM/DCOM, had het een aantal beperkingen. Met de komst van Windows 2000 kon MTS veel beter geïntegreerd worden. Daarbij werden ook nog een aantal mogelijkheden toegevoegd. Tegelijkertijd veranderde Microsoft de naam van MTS naar COM+ Component Services. De meeste ontwikkelaars dachten namelijk dat MTS alleen nodig was voor transacties, terwijl het veel meer in z’n mars heeft, en dus ook in applicaties die geen gebruik maken van transacties handig is. Omdat alle ontwikkelaars ondertussen wel doordrongen waren van het belang van COM, werd de naam COM+ gebruikt, zodat men sneller geneigd zou zijn naar MTS te kijken. COM+ Component Services is inmiddels een belangrijk onderdeel geworden van wat wel Enterprise applicaties genoemd worden. Bij Enterprise applicaties denken we meestal aan grootschalige applicaties voor grote bedrijven, maar ook kleine bedrijfscritische applicaties kun je onder Enterprise applicaties rekenen. Binnen .NET zijn de COM+ Component Services daarom bekend als Enterprise Services, ook om te benadrukken dat .NET niets met COM te maken heeft.

Een .NET COM+ component

Als je een .NET component maakt, maak je normaal gezien een of meerdere classes, die al dan niet afgeleid zijn van bestaande componenten. Wil je gebruik maken van COM+, dan moeten de classes afgeleid zijn van de class ServicedComponent die deel uit maakt van de System.EnterpriseServices namespace. De ServicedComponent class bevat alle functionaliteit die nodig is om gebruikt te kunnen worden binnen COM+, en iedere afgeleide class dus ook. Het skelet van een class die we kunnen gebruiken in COM+ ziet er in C# als volgt uit:

 1: using System;
 2: using System.EnterpriseServices;
 3:  
 4: namespace WinNetDemo
 5: {
 6:     public class ESDemoClass : ServicedComponent
 7:     {
 8:         //Code van de class hier
 9:     }
10: }

Om ervoor te zorgen dat COM+ altijd de correcte component gebruikt, moet je de assembly waar de component onderdeel vanuit maakt nog wel voorzien van een zogenaamde strong name. Dit is nodig om een component uniek te kunnen identificeren, en wordt door COM+ gebruikt om een CLSID te genereren die opgeslagen wordt in de Windows registry. Als een applicatie gebruik maakt van de component, wordt de juiste versie gebruikt op basis van die CLSID. Je kunt een strong name maken met sn.exe. Die maakt een bestandje met de .snk extensie. Door in AssemblyInfo.cs (voor C#) een referentie te maken naar dat bestandje zorg je dat de strong name gebruikt wordt als de component gecompileerd wordt. Je doet dit door de volgende regel in AssemblyInfo.cs te plaatsen, ervan uitgaande dat WinNetDemo.snk in de hoofdmap van je project staat in Visual Studio .NET (compileer je handmatig, dan kan dit dus anders zijn):

[assembly: AssemblyKeyFileAttribute("..\\..\\WinNetDemo.snk")]

Nu is het component in principe klaar om in COM+ gebruikt te worden. Daarvoor dient het echter wel geregistreerd te worden. Dit kan drie manieren, te weten handmatig met RegSvcs.exe, automatisch op het moment dat een applicatie voor het eerste gebruik maakt van de component, of door een aparte applicatie te maken waarmee je dit verzorgt. Het is voor COM+ belangrijk dat een component op een bekende locatie staat. Automatisch registreren is daarom niet iets wat je zomaar moet doen. Ook als je handmatig of via een applicatie registreert, is het verstandig om de component eerst te registreren in de Global Assembly Cache (GAC). Dit is een centrale plaats voor assemblies, die overigens wel meerdere versies van dezelfde assembly kan bevatten. Alle assemblies die in de GAC staan zijn door alle applicaties te gebruiken, en dat is voor COM+ eigenlijk wel belangrijk. Wat je wilt voorkomen is dat applicaties hun eigen lokale versies van een component gebruiken, en die afzonderlijk in COM+ registreren. Daarmee creëer je een chaos die je liever wilt vermijden.

Configuratie

Componenten configureren doe je over het algemeen via de Component Services snap-in van de Microsoft Management Console. Vanaf Windows 2000 is deze te vinden onder de Administrative Tools. De applicaties die actief zijn onder COM+ zijn te vinden in de COM+ Applications map die per computer beschikbaar is onder Component Services. Dit zijn niet zo zeer applicaties, maar groepen van componenten. Omdat die over het algemeen deel uitmaken van een applicatie zijn ze als zodanig gegroepeerd. Aan een applicatie kun je componenten toekennen door ze toe te voegen in de Components map.



Afbeelding 1, Een applicatie in Component Services

Via de Roles map kun je bepalen welke Windows account groepen gebruik kunnen maken van de componenten in de betreffende applicatie. In Afbeelding 1 zie je een voorbeeld van een applicatie met één component daarin, en waarvan de applicatie alleen toegankelijk is voor de Administrators groep. De eigenschappen van de applicatie zijn verder in te stellen door met de rechter muisknop op de applicatie te klikken en te kiezen voor Properties. Afbeelding 2 laat het scherm zien dat je dan te zien krijgt, nadat je gekozen hebt voor de tab Identity. In die tab kun je instellen onder welke gebruiker de component(en) uitgevoerd wordt. Dit kan een systeem account zijn, maar ook een specifieke gebruiker. Overigens is deze optie alleen beschikbaar als de applicatie ingesteld is als “server”, in plaats van “library”. In het eerste geval wordt de betreffende applicatie in een apart proces van de client applicatie uitgevoerd, en kan dus voor dat proces een andere gebruiker ingesteld worden. Zoals je ziet zijn er nog veel meer opties, maar het vergt een stevig boek om op alle mogelijkheden van Component Services in te gaan.



Afbeelding 2, Eigenschappen van een COM+ applicatie

Ieder component heeft ook eigenschappen die ingesteld kunnen worden. Je ziet hiervan een voorbeeld van de tab Activation in afbeelding 3. De Activation instellingen bepalen of object pooling en JIT Activation gebruikt worden. In dat laatste geval kun je ook bepalen hoe groot de pool mag zijn.



Afbeelding 3, Eigenschappen van een component

Instellingen in code

In principe worden de instellingen van een component bepaald door de beheerder. Veel van de instellingen hebben namelijk te maken met zaken die voor een ontwikkelaar niet van belang horen te zijn. Object pooling en JIT Activation bijvoorbeeld zijn instellingen die gebruikt worden bij het tunen van de performance, hetgeen geen ontwikkelactiviteit is. Een instelling die wel van belang is voor een ontwikkelaar is het al dan niet gebruiken van transacties. Het is eigenlijk gek dat een beheerder dit kan instellen, want dit is een vereiste die uit de opbouw van een applicatie of component komt. Een beheerder kan moeilijk bepalen of een applicatie wel of geen transacties moet gebruiken. Het handige van .NET is dat je de code kunt voorzien van attributen die aangeven wat de instelling van een component moet zijn. Wanneer een applicatie of component geregistreerd wordt in COM+, neemt COM+ die instellingen over. Vervolgens kan een beheerder daar eventueel nog wijzigingen in aanbrengen. Het biedt de ontwikkelaar echter wel een manier om een basisinstelling te kiezen. Met name op het gebied van transacties zou de beheerder deze instelling moeten respecteren. Voor andere instellingen kunnen de basisinstellingen als richtlijn fungeren. De code hieronder laat een aantal attributen zien die invloed uitoefenen op de instellingen van COM+.

 1: [ObjectPooling(MinPoolSize = 3,MaxPoolSize = 10,CreationTimeout = 30)]
 2: [Transaction(TransactionOption.Required)]
 3: public class ESDemoClass : ServicedComponent
 4: {
 5:     [AutoComplete]
 6:     public void DemoFunctie()
 7:     {
 8:         //Doe iets
 9:     }
10:  
11:     //Overige class code
12: }

In de code hierboven wordt ten eerste een instelling gegeven voor object pooling, waarbij aangegeven wordt wat de limieten zijn, en na hoeveel milliseconden een timeout plaats moet vinden. Ook wordt aangegeven dat het component alleen gebruikt kan worden als onderdeel van een transactie. De functie DemoFunctie is voorzien van het attribuut AutoComplete. Hiermee wordt aangegeven dat als alle code in die functie als normaal uitgevoerd wordt, dat die functie dan kan aangeven aan de transactie dat hij succesvol is uitgevoerd. Treedt er een fout op tijdens het uitvoeren van de functie, dan wordt de transactie daar automatisch van op de hoogte gesteld. De ontwikkelaar hoeft zich daardoor helemaal niet bezig te houden met de afhandeling van transacties, want dat regelt .NET verder.

Veel meer

Er is nog veel meer te doen met COM+ en .NET dan hier behandeld. Wat als een paal boven water staat is echter dat COM+ veel te bieden heeft aan .NET, en dat daarvan vanuit .NET gebruik van te maken is zonder dat de ontwikkelaar uit z’n weg moet gaan. Enterprise Services is erop gericht om de afhandeling van COM+ zaken over te laten aan .NET, zodat ontwikkelaars zich kunnen concentreren op de daarwerkelijke functionaliteit van een applicatie.

Dit artikel is eerder verschenen in Windows & .NET Magazine Benelux, november 2003 (huidige naam NetOpus)

<< vorige | ^ naar boven | overzicht | volgende >>
copyright 2000-2007 ASPNL