fredag, februari 17, 2012

Flera webapplikationer i en Web Role i Azure

En vanlig fråga jag får är hur man kan köra flera webapplikationer i en web role i Windows Azure. Det finns flera olika anledningar till varför man vill göra det och det finns också olika anledningar till varför man inte ska göra det.

Tänk att man har en site: www.contoso.com och till den vill du skapa ett antal sub-siter som t ex:

www.contoso.com/privatperson
www.contoso.com/företag
www.contoso.com/cms

Dessa vill man också säkra alla med ett SSL-certifikat. Respektive site ska också kunna utvecklas och hanteras separat. En nackdel är att man måste deploya hela paketet till Windows Azure. I och med att allt driftas i samma web role så kan man inte heller skala applikationerna separat utan allt skalas som en enhet. Det innebär att om företagsdelen av siten kräver extra kräm så skalas alla tre applikationer lika mycket. Som vanligt så finns det fördelar och nackdelar med allt.

Skapa projekt

Vi börjar med File – New Project, skapar ett Azure-Projekt och lägger till en Web Role. Den webapplikationen kommer att svara på rooten för siten, alltså www.contoso.com. Vi kommer manuellt att lägga till webapplikationerna senare.

image

När Azure-projektet är skapa lägger vi till två webapplikationer till samma solution. I mitt exempel använder jag mig av ASP.NET MVC 3. Skapa sedan en ny folder i Windows Explorer på samma plats som din solution och döp den till Publish.

image

Katalogen Publish ska användas som mål för en Web Deploy som vi nu ska ge oss in på.

Web Deploy

Om man använder ASP.NET MVC och Web Deploy så måste man också se till att få med de assemblies som refereras av projektet. I VS2010 SP1 finns en ny feature som gör allt jobb åt dig. Högerklicka bara på projektet och välj “Add deployable Dependencies…”. Välj sedan ASP.NET MVC så kommer att dll:er att kopieras med vid en web deploy.

image

För att göra en Web Deploy av webapplikationen, högerklickar man på applikationen i Visual Studio och väljer Publish. I dialogen som dyker upp väljer man File System som Publish method och sätter Target Location till en ny katalog i den Publish-katalog vi skapade tidigare.

image

Gör sedan samma sak för den andra webapplikationen.

I katalogen Publish ska det nu finnas två kataloger, en för varje webapplikation.

image

ServiceDefinition.csdef

För att lägga till de två siterna i webrollen behöver vi manuellt lägga till några saker i filen ServiceDefinition.csdef. Den filen innehåller nu information om den web roll vi lade till när vi skapade Azure-projektet, hur många instanser den ska ha, vilken storlek den har samt information om endpoints.

Till Site-taggen ska vi nu lägga till en VirtualApplication för respektive mvc-applikation vi vill deploya. När den är klar ska det se ut något i stil med:

  <WebRole name="RootWebApplication" vmsize="Small">
<
Sites>
<
Site name="Web">
<
VirtualApplication name="MvcApplication1" physicalDirectory="C:\junk\MultipleWebApplications\Publish\MvcApplication1" />
<
VirtualApplication name="MvcApplication2" physicalDirectory="C:\junk\MultipleWebApplications\Publish\MvcApplication2" />
<
Bindings>
<
Binding name="Endpoint1" endpointName="Endpoint1" />
</
Bindings>
</
Site>
</
Sites>
<
Endpoints>
<
InputEndpoint name="Endpoint1" protocol="http" port="80" />
</
Endpoints>
</
WebRole>


En Site kan innehålla flera VirtualApplications och varje VirtualApplication pekar på en katalog på disk. Den katalog den ska peka på är den samma som vi tidigare gjorde en web deploy till.



Ctrl – Shift – B => Build succeeded och dags att publicera till Azure! Glöm inte att ändra osFamily="2" så att web rollen kör Windows Server 2008 R2. Observera att varje gång man gör en förändring i MvcApplication1 eller MvcApplication2 så kommer dessa förändringar inte med om man bygger och publicerar till Auzre. För att få med en förändring måste man först göra en Web Deploy för varje webapplikation.



I mitt exempel ligger alla tre webapplikationerna i samma Visual Studio Solution men det är så klart inte något krav. I och med att Azure-projektet pekar ut en lokal folder på disk, som den ska sätta upp som en ny applikation i IIS, kan respektive applikation hanteras helt separat.



I IIS i Windows Azure skapas det en site och i den skapas det två applikationer:



image









MSBuild för automatisering









Det sista steget är att lägga till en Target för MSBuild så att varje gång du bygger webapplikationerna görs en Web Deploy till Publish-biblioteket som vi skapade tidigare.



För att editera en csproj-fil i Visual Studio så högerklickar man på projektfilen och väljer Unload Project. Sedan högerklickar man igen på projektfilen och väljer Edit.



I den första <PropertyGroup> (som gäller för alla olika konfigurationer och plattformar) lägger vi till en variabel som heter PublishDestination som innehåller namnet på den katalog vi skapade tidigare som är målet för vår web deploy.



<PublishDestination>Publish</PublishDestination>



Sedan lägger vi till följande Target:


<Target Name="PublishToFileSystem" AfterTargets="AfterBuild" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<
Error Condition="'$(PublishDestination)'==''" Text="The PublishDestination property must be set to the intended publishing destination." />
<
ItemGroup>
<
PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</
ItemGroup>
<
Copy SourceFiles="@(PublishFiles)" DestinationFiles="@(PublishFiles->'$(SolutionDir)$(PublishDestination)\$(TargetName)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
<
Message Importance="high" Text="Deploying to: $(SolutionDir)$(PublishDestination)\$(TargetName)\"></Message>
</
Target>


Högerklicka på projektfilen igen och välj Reload Project.


Det här måste också göras för den andra webapplikationen.


That’s it! Varje gång vi bygger projektet kommer nu alla tre siter att byggas och de två siter som ska bli Virtuella Applikationer kommer att Web Deployas, med refererade filer, till rätt ställe på lokal disk så att Azure-projektet kan ta med dem i en deploy.