Introduction
Everyone who compared Windows Azure pricing with other hosting options knows that Windows Azure can be more expensive than
shared hosting. Windows Azure offers great scalability and reliability but for a small web site owner it might be hard to
decide if features actually justify the price.
Here are several tips that may help you build your Windows Azure web site cost effectively.
You can pack everything in one Web Role
A Role in Windows Azure is similar to a Virtual Machine, and is actually one of the most expensive pieces of the puzzle.
Let's say you are building a web site, a web service, and some back-end processing module. In most tutorials Microsoft tells
you that you'd need three Roles: a Web Role for your web site, another Web Role for your web service, and a Worker Role
for the back-end processor. Microsoft also advise you to have at least two instances of each Role for reliability purposes,
which is a good thing to do, but will bring you to six instances in total for your rather small web site. Sounds like overkill,
but don't worry, there are ways to deal with that. Most likely, you can pack your whole system in one Role (and deploy two
load-balanced instances of it for reliability).
Here is an example of putting a public web site (using http), a user management web site (using https on standard port 443),
a web service (using https on custom port 12345), and a scheduled worker processor in one Web Role.
Build projects for your web sites (most likely as a Web Application projects) and the worker DLL project the usual way.
Create a Windows Azure Web Role project for your public web site, having Visual Studio create a ServiceDefinition.csdef
file with everything you need to run public web site in Windows Azure.
Now you need to teach Azure deployment tool how to transfer your additioinal web applications to Windows Azure and how to
configure the IIS to run them the way you want. You do that by changing the ServiceDefinition.csdef file, like this:
<WebRole name="MySingleWebRole" vmsize="Extra small">
<Sites>
<Site name="MyWebSite" physicalDirectory="..\MyWebSite">
<Bindings>
<Binding name="BindingPublic" endpointName="EndpointPublic" hostHeader="www.example.com" />
<Binding name="BindingPublic2" endpointName="EndpointSecure" hostHeader="www.example.com" />
</Bindings>
</Site>
<Site name="MyUserManagement" physicalDirectory="..\PublishedSites\MyUserManagement">
<Bindings>
<Binding name="BindingAdmin" endpointName="EndpointSecure" hostHeader="admin.example.com" />
<Binding name="BindingAdmin2" endpointName="EndpointPublic" hostHeader="admin.example.com" />
</Bindings>
</Site>
<Site name="MyService" physicalDirectory="..\PublishedSites\MyService">
<Bindings>
<Binding name="BindingService" endpointName="EndpointService" hostHeader="service.example.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="EndpointPublic" protocol="http" port="80" />
<InputEndpoint name="EndpointSecure" protocol="https" port="443" certificate="wwwssl" />
<InputEndpoint name="EndpointService" protocol="https" port="12345" certificate="servicessl" />
</Endpoints>
<Certificates>
<Certificate name="wwwssl" storeLocation="LocalMachine" storeName="My" />
<Certificate name="servicessl" storeLocation="LocalMachine" storeName="My" />
</Certificates>
</WebRole>
Here we added two more Site elements and pointed them to appropriate physical directories where the project files are. In
this example MyWebSite physical directory points to the actual Visual Studio project folder - it is listed in the Web Role's
configuration, so the deployment tool knows that it needs to build the project and deploy only the files needed at runtime.
You are not required to add your additional projects into the same solution where you have the Azure project. It does not
matter where your additional files are, it is just more convenient to have everything in one solution.
In any case, don't point physical directories for your additional web sites to actual folders of your Visual Studio projects.
If you do so, the deployment tool will copy EVERYTHING in those folders to the web server, including all source files. Web
sites will work, but you probably want to keep the source code on your own machine and not to copy it to production server
on Windows Azure.
Instead, for each additional web site publish it to the file system, targeting some folder in the same directory structure
where your main web site resides. (You do that by selecting "Publish" item from the "Build" menu in
Visual Studio and choosing "File System" Publish Method.) In our example we created \PublishedSites folder next
to the Azure project folder and published MyUserManagement and MyService sites to the \PublishedSites\MyUserManagement
and \PublishedSites\MyService
folders. As those folders now contain only files needed at runtime we can safely
use them as physicalDirectory parameter. Note, that path in physicalDirectory value is relative to the location of the ServiceDefinition.csdef
file.
In this example we use three different ports, so we declare three endpoints - EndpointPublic for unsecured public access
through standard port 80, EndpointSecure for https access on standard port 443, and EndpointService for https access on
port 12345. We also instruct IIS to use two different SSL certificates declared as wwwssl and servicessl.
Replacing Worker Role
If you have some code that should run at a regular interval and do back-end processing, you can add that code to your single
Web Role.
In your web application project add a class inheriting Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint
class. Let's
call that class WebRole
:
public class WebRole : RoleEntryPoint
{
}
Than override Run
method. There is one strange thing that you should remember: method Run should never return
- in its simplest implementation the thread in which the Run
method runs should sleep forever. In our case
we want it to wake up periodically, do some useful work and go back to sleep:
public override void Run()
{
while (true)
{
try
{
DoSomeWork();
Thread.Sleep(30000);
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
System.Threading.Thread.Sleep(30000);
}
}
}
Another thing to note - all instances of your Web Role will have this worker thread running, doing the work concurrently.
Make sure this is what you need. Also, if the worker process checks some external resources it might make sense to randomize
the sleeping interval to reduce chances of collision.
SQL Azure is not expensive
SQL Azure is actually less expensive than SQL Server databases offered by many hosting companies. Just make sure you don't
use incompatible SQL statements. For example, following Transact-SQL features are not supported by SQL Azure Database:
- Common Language Runtime (CLR)
- Database file placement
- Database mirroring
- Distributed queries
-
Distributed transactions
- Filegroup management
- Global temporary tables
- SQL Server configuration options
-
SQL Server Service Broker
- System tables
- Trace Flags
Avoid Azure Table Storage
At first glance Azure Table Storage looks like cheaper alternative to SQL Azure, but because you are billed by storage amount
and by number of requests it can cost you a lot if you retrieve or write data from/to the storage frequently. It also has
serious feature limitations, like inability to create additional indexes, absence of any search functionality. It can even
distort your data because it uses XML under the hood - for example you can lose some white spaces. I would suggest using
Table Storage only for huge amounts of rarely needed data, and even in that case evaluating SQL Azure first.
Azure Caching Service is expensive
Try using conventional in-memory cache - it's free and gives you more space than Windows Azure Caching Service. Use Azure
Caching Service only if you really need singleton-style cache access across the web farm, like for User Session data.
Use building blocks from Windows Azure Marketplace
Check Windows Azure Marketplace at https://datamarket.azure.com/browse/Applications?Price=Free
to see if there is a free service or application that can add value to your web site.
For example, there is the Microsoft Translator
service which delivers automatic translation (machine translation) of a text into a specified language using simple API
- free for up to 2,000,000 characters/month.
Another example, ElasticWCM is described as a content management system, but in
fact is a free set of building blocks that you can add to any existing ASP.NET web site to enhance it with pretty flexible
content management features.
Offers like these start appearing on Azure Marketplace, providing cost-effective way to utilize Windows Azure.