Archive for Windows Azure
We’ve seen a big increase in the number of requests to run Loupe Server on Azure in the last few months. The good news is this has been possible ever since Azure introduced Virtual Machine support – as long as you installed SQL Server on the VM. The better news is that as of Loupe 3.5.6 you can use SQL Azure. This provides a lower cost, simpler to maintain way of hosting Loupe Server in Azure.
To get up and running you’ll need to provision:
- One Windows 2012 R2 Virtual Machine: This will host the Loupe Server software – including the web site and Windows service.
- One SQL Azure Database: You can create just the Server instance and user at this time and let Loupe create the database if you like.
For our testing, we used a Small instance VM and a Web instance DB with a limit of 1GB. This means the operating cost would be just $77 per month (a lot less if you have other Azure services). A small instance is pretty tight – so for a bit more room to grow pick a Medium instance and it’s still just $122 per month.
Preparing the SQL Azure Database
When you create a new SQL Azure Database you can pick an existing SQL Server on your account or create a new SQL Server. It’s important you create the SQL Server and the Virtual Machine in the same Azure region for the best performance. When you create the database you’ll also specify the SQL Administrator account which you’ll use during the installation.
In this screenshot you can see we’ve created a database on a new server which has been assigned the name “drhv5sztg2″. In the lower right you’ll see the full server name in the management URL which is what we’ll need for the Loupe Server to connect to it: drhv5sztg2.database.windows.net.
Once the database has been created you’ll need to adjust the access rules for it to be sure the Virtual Machine can get access to it. The simplest way to do this is to enable the Azure Services access.
In the example above we’ve enabled Windows Azure Services, and in this case my home address and one of our data centers, just for some additional testing I performed. If you want to access the database from your own desktop or data center, you can add the relevant IP addresses to the list.
Setting Up the Virtual Machine
To start, request a new Virtual Machine from Microsoft’s image library. We recommend the latest Windows server image – Windows 2012 R2 at this moment. You’ll want to create this as a new cloud service which will let you assign the public name your Loupe Server. Be sure to pick the same Azure region that your database server is in.
In the example above the Loupe Server’s cloud service has the name installhubtest.cloudapp.net. If you want to use a different name you can set up a CNAME on your domain and point it at this name.
Once the VM is running you can configure the necessary endpoints. These create connections through the Azure firewall infrastructure to map traffic from the public IP address to your virtual machine. To enable all Loupe capabilities including Live Sessions we’ll need to set up three endpoints:
- HTTP: The web server itself. There is an endpoint in the list for this in Azure which has the correct port. You may also choose to add HTTPS if you want to install an SSL certificate.
- Loupe Agent: The port used for Agents to send live update data to the server. By default, this is port 29971.
- Loupe Client: The port used for Clients to subscribe to live update data from the server. By default, this is port 29970.
The example above shows all three endpoints configured, along with the default endpoints Azure makes so you can remotely access and manage the server.
Once you’ve requested the VM from Microsoft’s image library and it has started, log in using RDP to set it up just like you would your own virtual or physical server. With Windows 2012 (and 2012 R2) all of the dependencies for Loupe are readily available. To install all of the dependencies, select the following roles:
- Application Server
- Web Server (IIS)
Customize the Application Server role by selecting Web Server (IIS) Support under Role Services.
Once this configuration has been completed, you’re ready to download the Loupe installation to the server and run it normally.
Configuring Loupe Server
After the Loupe installation completes it will automatically launch the Loupe Server Administrator. This will in turn start the first time configuration wizard.
When configuring the SQL Server, be sure to provide the complete DNS name of the SQL Azure Server. Enter the database name you previously created (or another name, in which case the database will be automatically created for you) and select SQL Authentication, providing the credentials from when you created the database. The schema will be loaded into the database by the Loupe Server Administrator at the end of the wizard.
When asked for the Web Site configuration, provide the public name of your cloud service that was assigned when the Virtual Machine was created. This information is used to create links in emails and some security features.
Enable the Live Sessions feature so you can view log sessions in real time. If you want you can select different ports than the defaults, in which case you’ll need to change the Azure VM endpoint configuration that was previously set up.
Once the wizard completes the only other thing to configure that’s Azure specific is the time zone – since all Azure VM’s have their time zone set to UTC you’ll inevitably want to tell Loupe to use a different default time zone. To do this, select the Repository node in the tree view.
In the above example I’ve changed the default to US Eastern Standard Time which is the time zone we use for our internal reporting.
Accessing Your Loupe Server
Before you can log into your Loupe Server the first time you’ll need to create an administrator. Using the Loupe Server Administrator, click on Users and you can add your first user. It will default to being an Administrator. Once you’ve added this user you can use the web interface to add the rest of the users you need.
Now that you’ve set up your server, you can access it anywhere in the world using the DNS name set up for the Azure service. You should see the web page come up within 15 seconds (giving some time for it to spin up the application for the first time). If it doesn’t show up, go back and verify that you set up the HTTP endpoint for the Virtual Machine.
Log in using the administrator account you configured and you’ll be greeted with a blank dashboard. As you send sessions to it you’ll see the applications show up on this dashboard.
Limitations and Notes Unique to Azure
There are a few caveats to hosting in Azure in the configuration described above. The first is that Microsoft will automatically restart the host underlying the virtual machines every four to eight weeks, generally without notice. When they do this your Loupe server will be unavailable for 20 minutes or so. This doesn’t affect the SQL Azure database but will affect the virtual machine.
Additionally, due to a limitation in SQL Azure compared to SQL Server there is a delay in performing background processing of up to 15 seconds. This will cause a short delay before dashboard metrics and email alerts are generated compared to using a full SQL Server.
A friend of mine posted to Twitter a bit ago that he was having trouble dealing with HttpCompression on Windows Azure. Specifically, only certain default MimeTypes were being compressed (like ASPX and CSS), while other important ones like JSON and SOAP were not.
During another Azure project, I also ran into an issue where logins stopped working after upgrading to
Azure OS 2.X Azure SDK 1.3. It turns out that there is a bug in that release that doesn’t allow configuration inheritance for the MachineKey, and the workaround was to manipulate the server configuration in the RoleEntryPoint.
Since I’m already having to manipulate the server config to synchronize the MachineKey settings, I thought I’d whip up some code real quick to solve this problem during the same process, using the httpConpression topic on IIS.net as a guide.
If you don’t already have a RoleEntryPoint in your app… well, you should. Copy the code below into a new class file in your main application, and add a reference to Microsoft.Web.Administration.dll, as specified here. You’ll also notice Gibraltar-specific code peppered throughout… this is all that you need to get Gibraltar working on Windows Azure (as long as you’re also using the tip from my previous post as well).
(The code is long, and it’s in VB… because that’s the language this particular app was in. If you need it converted to C#, you can do so here.
UPDATE: My colleage Kendall pointed out that the role event handlers should be declared at the very beginning, and that, even though the RoleInstance’s OnStart event is called on a separate thread from the main app, it should still run the WarmUp loop on a separate thread, so that the function can return MyBase.OnStart() and exit properly. Good call.
Imports System.Linq Imports Microsoft.WindowsAzure.Diagnostics Imports Microsoft.WindowsAzure.ServiceRuntime Imports Microsoft.Web.Administration Imports System.Threading Namespace Fon.Apps Public Class WebRole Inherits RoleEntryPoint Public Overrides Function OnStart() As Boolean ' For information on handling configuration changes ' see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. AddHandler RoleEnvironment.Changing, AddressOf RoleEnvironment_Changing AddHandler RoleEnvironment.Stopping, AddressOf RoleEnvironment_Stopping Gibraltar.Agent.Log.SendSessionsOnExit = True Using server As New ServerManager() 'Cycle through the sites and set the MachineKey for each one. For Each site In server.Sites Dim siteConfig = site.GetWebConfiguration() 'Get the appSettings section Dim appSettings = siteConfig.GetSection("appSettings").GetCollection().ToDictionary(Function(e) DirectCast(e("key"), String), Function(e) DirectCast(e("value"), String)) 'Reconfigure the machine key Dim machineKeySection = siteConfig.GetSection("system.web/machineKey") machineKeySection.SetAttributeValue("validationKey", appSettings("validationKey")) machineKeySection.SetAttributeValue("validation", appSettings("validation")) machineKeySection.SetAttributeValue("decryptionKey", appSettings("decryptionKey")) machineKeySection.SetAttributeValue("decryption", appSettings("decryption")) Next 'Turn on compression for JSON and SOAP. Dim config As Configuration = server.GetApplicationHostConfiguration() Dim httpCompressionSection As ConfigurationSection = config.GetSection("system.webServer/httpCompression") Dim dynamicTypesCollection As ConfigurationElementCollection = httpCompressionSection.GetCollection("dynamicTypes") Dim e1 As ConfigurationElement = dynamicTypesCollection.CreateElement("add") e1("mimeType") = "application/json" e1("enabled") = True dynamicTypesCollection.AddAt(0, e1) Dim e2 As ConfigurationElement = dynamicTypesCollection.CreateElement("add") e2("mimeType") = "application/json;charset=utf-8" e2("enabled") = True dynamicTypesCollection.AddAt(0, e2) Dim e3 As ConfigurationElement = dynamicTypesCollection.CreateElement("add") e3("mimeType") = "application/soap+xml" e3("enabled") = True dynamicTypesCollection.AddAt(0, e3) server.CommitChanges() End Using 'Poor man's Application Warm-up here Tasks.Task.Factory.StartNew(Sub() Try While (True) Trace.WriteLine("Warming up web site...") Dim webClient As New Net.WebClient() webClient.DownloadString("http://mysite.com/WarmUp.ashx?WarmUp=True") Thread.Sleep(TimeSpan.FromMinutes(9)) End While Catch ex As Exception Gibraltar.Agent.Log.RecordException(ex, "WindowsAzure.WebRole.Startup", True) End Try End Sub) Return MyBase.OnStart() End Function Private Sub RoleEnvironment_Stopping(sender As Object, e As RoleEnvironmentStoppingEventArgs) Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.") End Sub Private Sub RoleEnvironment_Changing(sender As Object, e As RoleEnvironmentChangingEventArgs) ' If a configuration setting is changing If e.Changes.Any(Function(change) TypeOf change Is RoleEnvironmentConfigurationSettingChange) Then ' Set e.Cancel to true to restart this role instance Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.") e.Cancel = True End If End Sub End Class End Namespace
You might have noticed the While loop that cycles every 9 minutes and makes a request to a specific website. Though the actual site details have been abstracted out, this is a trick that I use to keep my application “warmed up,” and is a variation on the technique used by Christian Weyer.
For the MachineKey part, you’ll also need to add the following entries to the appSettings section of each of the web.configs in your Role, being sure to replace your values where appropriate:
<add key="decryption" value="Auto" /> <add key="decryptionKey" value="YOURVALUEHERE" /> <add key="validation" value="SHA1" /> <add key="validationKey" value="YOURVALUEHERE" />
You’ll also notice that it’s also pretty easy to add additional MimeTypes to compress. Just continue to copy the pattern for any of the items you think are missing. Be sure not to add ones that don’t already exist, or you’ll likely crash your role.
Anyways, I I hope that helps some of you that are trying to resolve various Azure issues.