Vi har en applikation kørende på en maskine i dmz, der periodisk checker for jobs i en kø (sql-tabel). Når der findes et job, eksekveres jobbet. Applikationen loader et par assemblies fra vores web-server, og kalder det bestilte job. Ideen er god: Web-klienter mærker ikke til at de starter et batch-job, og vi kan opdaterer webserveren uden at skulle tænke på jobkø-applikationen – den loader bare alle assemblies inden hvert job – eller gør den?
Efter at vi har migreret til TFS 2008, og opdateret webfarmen til .NET 3.5, stopper vores jobkø. Den har store problemer med at starte de reflekterede metoder, og vores log er fyldt med kryptiske fejl. Hvad gik galt? Jeg er stadig ikke helt sikker, men problemet har noget at gøre med de dynamisk loadede assemblies afhængigheder. De går tabt i det eksisterende system, som fungerer således:
- Dll'er kopieres over på job-maskinen
- Assembly.CreateInstance() instantierer et objekt, der castes til et interface
- JobStart-metoden kaldes på interfacet
Der er sket et eller andet i frameworket (eller vores tfs-migrering), der gør at vi ikke længere kan oprette en instans på den måde. Så var det jeg faldt over en artikel hos Kodehovedet.dk – her gennemgås AppDomain, og jeg kan se en løsning på alle vores versionsproblemer. Her er mit første forsøg med AppDomain:
[code=csharp]AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = @"C:\........\bin\Release"; setup.ShadowCopyFiles = "true"; setup.CachePath = @"c:\dmz"; start: AppDomain domain = AppDomain.CreateDomain("New AppDomain", null, setup); IJob application = (IJob)domain.CreateInstanceAndUnwrap("CLibA", "CLibA.JobA"); DateTime shadowStamp = DateTime.Now; while (Directory.GetLastAccessTime(setup.ApplicationBase) <= shadowStamp) { application.DoTheThing(); Thread.Sleep(1000); } goto start; [/code]
Som det ses, så bruges CreateInstanceAndUnwrap metoden til at lave instansen af vores job-objekt. Ved at bruge AppDomainSetup, og sætte ShadowCopyFiles = "true" (strengen ikke bool), laver objektet automatisk en kopi af assemblyen, og på den måde undgår vi at applikationen låser assemblyet, så vi kan opdaterer webserveren uden at stoppe "job-serveren".
Det virker her i mit test-setup – dagen i morgen, vil vise om det holder i produktion.