This is the third post of the
Umbraco on Windows Azure series. In the
first post, I introduced Umbraco CMS, Windows
Azure and the reason why you would like to host your Umbraco
site on Windows Azure, with a brief manual installation
walkthrough. In the second post I
presented the open-source helper Windows Azure Accelerator for
Umbraco, which let you to deploy the site on Windows Azure in
less than an hour. In this post, we'll see how to solve its
thousands daily storage transactions issue.
Umbraco Accelerator Lite
When I first encountered the
drawbacks described in the previous post, it seemed to me that
using Umbraco on Windows Azure would cost more than using a
dedicated hosting solution. I couldn't believe that no other ways
to handle the synchronization existed. Something had to be done, so
I started to work on the problem.
After some days of investigation,
monitoring and rework, I figured out an alternative solution that
involved a file-based notification approach:
-
each time a change occurs on the
local file system, a sentinel file is created automatically, using
a simple Umbraco extension attached to its internal events;
-
when a file is changed on the
blob storage, another sentinel file has to be created (either
automatically, when the change is made by the monitor process, or
manually, if a file is uploaded via the Accelerator deployer or a
storage explorer tool);
-
the background monitor
periodically checks for the existence of one of those files. If any
exists, the synchronization take place.
Unfortunately, this solution leaded
to an even higher transaction usage: checking for file
existence on the blob storage involved a transaction and, in
addition to check for the sentinel, the blob listing had to be
retrieved too (another transaction)! It also introduced
multi-instance race conditions when dealing with the sentinel file
on the storage. No way from here...
Looking for other paths, I noticed
that frequently querying the database didn't cost so much, compared
to transaction usage. So here's the new idea, combining the
previous file-based approach and SQL Azure:
-
each time a change occurs on the
local file system, a sentinel file is created automatically, using
a simple Umbraco extension attached to its internal events;
-
instead of checking for blob
sentinel file existence, the last update timestamp is retrieved
from a custom table in the Umbraco DB on SQL Azure; this value is
updated either automatically, when the change is made by the
monitor process, or manually, if a file is uploaded via the
Accelerator deployer or a storage explorer tool.
-
the background monitor
periodically checks for the existence of the local sentinel file
and compare the last blob update timestamp. If the file exists or
the blob storage changed since the last check, the synchronization
take place.
Bingo! No more void storage
transactions just to check whether to perform a sync or not.
Of course, transactions to retrieve blob listing and to
upload/download files have still to be done, but just when
required.
The solution is optimal and
required for blob-to-local synchronization. In order to minimize
SQL Azure usage, the file-based approach has been maintained for
local-to-blob synchronization. This behavior could have been
abandoned and the synchronization could have been performed as in
the original Accelerator for Umbraco: that's because accessing the
local file system doesn't cost anything. But while optimizing, why
not reducing also file system access and avoid too much disk I/O,
which could slow down instance performance? This way, in the
Accelerator Lite, the monitor just checks for local modifications
only when the sentinel file exists. Otherwise, it just do
nothing!
Another little optimization may be
done, noticing that (probably), after the initial setup phase and
configuration, local files changes won't be so frequent. So,
instead of running the synchronization process each second, it
could be slowed down (and made externally configurable in the Web
Role configuration file).
Download and try it
I'm currently running this blog and
another one with Umbraco on Windows Azure and the Umbraco
Accelerator Lite, for 20 days now.
If you want to experiment it, give
feedbacks, suggestions, contributes… here you can download all the
stuff:
-
Umbraco Accelerator Lite v1.0beta
- Umbraco Accelerator Notifier Extension (binaries and
sources)
- Umbraco Accelerator Lite webrole (sources)
- SiteDeployer tool (binaries and sources)
Please, remember this is a beta version. It should work fine but, prior
to use it for production, test it carefully in a development
environment.
Currently, I tested it in a single website / single
instance configuration, with Umbraco v4.7.1.1. It has been
designed to support multi-site/multi-instance scenario, but I
haven't tried it yet. Also, at present, it cannot be run with the
original Windows Azure Accelerator for Umbraco wizard
scripts. I'm working on the integration of the my work with the
official accelerator but, at present, you have to do some manual
work in order to setup it.
In future posts, we'll see detailed step-by-step instructions on
how to install and configure it.
Installation steps overview
For those who want to try it now, here there are the main tasks
to do (for details on some of the operations, you can
refer directly to the Azure Accelerator for
Umbraco Getting Started page and Deployment guide).
- On Windows Azure, activate a Storage service and an SQL Azure
Server
- In your local SQL Server, create a DB user and 2 empty
databases, one for Umbraco backend and one for ASP.NET session.
Give the newly created user a dbOwner role on both databases. Run
the SQL scripts contained in UmbracoAcceleratorLite\
SiteDeployer\db\InstallSqlState.sql to create the ASP.NET
session DB.
- Install a local Umbraco website pointing to the empty
Umbraco DB created at step 2. Complete the basic Umbraco
setup.
- Copy UmbracoAcceleratorNotifier.dll extension to the Umbraco
\bin folder
- Create the Umbraco Accelerator Lite custom table in
the local Umbraco DB and prepare it for SQL Azure (you can run the
SQL scripts contained in UmbracoAcceleratorLite\
SiteDeployer\db\SqlAzure.AcceleratorLiteScripts.sql)
- In SQL Azure Server, create the same DB owner user you
created for the local databases (you can edit the SQL scripts
contained in UmbracoAcceleratorLite\
SiteDeployer\db\SqlAzure.UserSetup.sql)
- Using a third party tool migrate the two DBs in SQL Azure (you
can use the SQL Azure Migration Wizard or RedGate SQL Azure Backup)
- Edit Umbraco web.config file in order
to make it pointing to the SQL Azure DBs
- Use the SiteDeployer tool to copy your local Umbraco
installation to the Azure blob storage. Use a domain name of type
"<name>.cloudapp.net".
- In Visual Studio 2010, open the web role solution, configure
its data storage string in order to point to your Azure Storage
service and build the Service Deploy package.
- In Windows Azure Management Portal, create a new Hosted service
with the built package, giving it the same DNS name of the uploaded
Umbraco site, <name>(.cloudapp.net).
- In about 20 minutes your Umbraco site will be reachable at the
domain you specified ("http://<name>.cloudapp.net").
In case of issues or problems, let me know (or wait for the
step-by-step detailed instructions).