by Steve Marx via Steve Marx's blog on 4/20/2010 9:55:35 PM
In this post, I’ll show how you can run your own instance of Hosted Web Core (HWC) in Windows Azure. This will give you the basic functionality of a web role, but with the flexibility to tweak advanced IIS settings, run multiple applications and virtual directories, serve web content off of a Windows Azure Drive, and more.
If you want to try this out yourself, you can download the full Visual Studio 2010 solution from Code Gallery.
The code I share in this blog post will work today, but I should point out that Windows Azure will provide the full power of IIS in the future, without the need for you to manage your own Hosted Web Core process.
I should also point out that by running HWC yourself, you’re taking responsibility for a lot of things that are completely abstracted and automated away in the existing Windows Azure web role. Use this code only if you’re comfortable managing your own IIS configuration files and debugging HWC errors.
IIS Hosted Web Core is what Windows Azure uses to power web roles. It runs web applications using the same pipeline as IIS, but with a few restrictions. Specifically, Hosted Web Core can only run a single application pool and a single process. It also does not include the Windows Process Activation Service (WAS). If you’re interested in learning more about using Hosted Web Core, I recommend blog posts by CarlosAg and Kanwaljeet Singla, in addition to the MSDN documentation.
As I discussed in my post “Using Other Web Servers on Windows Azure,” the flexibility of worker roles with endpoints means you can run all sorts of servers in Windows Azure. The technique I described there has been used to run Apache, Tomcat, Jetty, Mongrel, WEBrick, SMTP servers, FTP servers, and more. Running Hosted Web Core is no different, but because it’s already installed on Windows Azure VMs, there’s no need to upload it with your package.
The only difficult part is the HWC configuration, some of which needs to be done at runtime.
To launch Hosted Web Core, we need to pass two paths to WebCoreActivate: the path to applicationHost.config and the path to the root web.config. Many of the settings in these configuration files are fixed, but some will need to change based on information available at runtime. For example, the port I need to bind to and the location of my web content won’t be known until runtime.
WebCoreActivate
applicationHost.config
web.config
I decided to implement a very simple parameterization scheme. Throughout applicationHost.config and web.config, I used parameters like {approot}, which get replaced by simple string substitution at runtime, based on a NameValueCollection of parameters and values.
{approot}
NameValueCollection
Below is the code that writes out the parameterized configuration files. This code runs in OnStart():
OnStart()
var parameters = new NameValueCollection(); // "DiagnosticStore" is automatically inserted and is where the diagnostic monitor will look for these var diagnosticStore = RoleEnvironment.GetLocalResource("DiagnosticStore").RootPath; parameters["LogFilesDirectory"] = Path.Combine(diagnosticStore, "LogFiles"); parameters["FailedReqLogFilesDirectory"] = Path.Combine(diagnosticStore, "FailedReqLogFiles"); parameters["iisCompressionCacheDirectory"] = RoleEnvironment.GetLocalResource("iisCompressionCache").RootPath; var approot = Environment.GetEnvironmentVariable("RoleRoot") + @"\approot"; parameters["approot"] = approot; var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["HttpIn"].IPEndpoint; parameters["address"] = endpoint.Address.ToString(); parameters["port"] = endpoint.Port.ToString(); parameters["aspNetTempDirectory"] = RoleEnvironment.GetLocalResource("aspNetTemp").RootPath; parameters["applicationPoolName"] = "{" + Guid.NewGuid().ToString() + "}"; parameters["machineKeyElement"] = RoleEnvironment.GetConfigurationSettingValue("machineKeyElement"); string configPath = RoleEnvironment.GetLocalResource("Config").RootPath; // substitutes in the above parameters HWCConfig.WriteConfigFile( parameters, Path.Combine(approot, "applicationHost.config"), Path.Combine(configPath, "applicationHost.config")); // substitutes in the above parameters HWCConfig.WriteConfigFile( parameters, Path.Combine(approot, "web.config"), Path.Combine(configPath, "web.config"));
Making sure you have a working applicationHost.config and web.config is probably the hardest part of building this HWC worker role. As a starting point for my configuration files, I took the actual files from a web role. (I wrote some code to hunt around on the VM’s local storage and found the ones in use.) From there, all I did was fix some hardcoded paths (substituted %windir% for d:\windows in a number of places) and comment out a couple lines that initialize the Windows Azure runtime. (This has already done by the time my code runs in the worker role.)
%windir%
d:\windows
Once the configuration files are written, we simply need to launch Hosted Web Core. This involves a little bit of P/Invoke, since HWC is a native DLL. Read HWCPInterop.cs in the sample code for the details.
HWCPInterop.cs
To use the sample code, you need to do only two things:
Websites
machineKeyElement
ServiceConfiguration.cscfg
With the full sample code from Code Gallery, you should be able to mimic the functionality of a web role with no real difference. The whole point of this exercise, though, is to enable some additional scenarios. In future blog posts, I’ll explain how to use this code to do the following:
MaxConcurrentRequestsPerCPU
You can download the full Visual Studio 2010 solution from Code Gallery.
Original Post: Build Your Own Web Role: Running Hosted Web Core in Windows Azure
The content of the postings is owned by the respective author. AzureFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on AzureFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.