3. Updating your
HTTP handler to use local storage
You’re going to modify your
HTTP handler to check in local storage to determine whether the
requested file exists already. If the file doesn’t exist, then you’ll
retrieve the MP3 file from BLOB storage and store it in local storage.
Finally, you’ll write the file back to the client from your local
filesystem. The following code shows how you modify the ProcessRequest
method in this listing to use local storage.
public void ProcessRequest(HttpContext context)
{
string blobName = context.Request.Path.Trim('/');
var mp3Cache = RoleEnvironment.GetLocalResource("mp3Cache");
string localFilePath = mp3Cache.RootPath + blobName;
if (!File.Exists(localFilePath))
{
var blobData = GetBlob("chrisoriginals", blobName);
File.WriteAllBytes(localFilePath, blobData);
}
context.Response.ContentType = "audio/mpeg";
context.Response.WriteFile(localFilePath);
}
Using the local
storage mechanism in your HTTP handler improves performance by serving
the requested file from local storage, rather than always having to
retrieve the file from BLOB storage first. Although performance is
improved, if the file is changed in BLOB storage, the file that you’ll
serve will be out of date. Let’s look at how you can keep the
performance improvement but serve the latest content even if the file
has changed in BLOB storage.
Tip
Although this sample is
focused on web HTTP handlers, this technique can easily be used in
worker roles. I currently use this technique with a Windows Azure
MapReduce solution that I’ve built.
4. Checking
properties of a BLOB without downloading it
If you were to use the HTTP HEAD verb
instead of the GET verb, you
could check the properties of the file without downloading the file. Figure 2
shows the output of a HEAD request.
In figure 2, the Last-Modified tag shows us the last time the file was updated in
BLOB storage. By comparing the header value to the local value in your
file properties, you know whether the file has changed.
In figure 2, you’ll notice that there’s a tag called x-ms-request-id. Every request made is assigned a unique
identifier (GUID) that’s returned in the response. Every request and
response is logged by Microsoft; if you’re experiencing issues, you can
always pass this ID with a support request—providing the ID lets
Microsoft easily investigate any issues you have.
|
The listing that follows shows
the code for the console application shown in figure 2.
Listing 1. Showing the output of a HEAD request
In the code example shown in listing 1, you make the same request that you’ve made before, but
it’s a HEAD request instead of a GET
request. You’re making a HEAD request for
the file podcast01.mp3 in the ChrisOriginals container in your
development storage account . At
you loop through all the returned headers, outputting the header key and
value to the console screen.
Using the Storageclient
Library
In listing 1,
you retrieved the last modified time using the REST API directly,
although you could’ve used the StorageClient library. The following code
performs a HEAD request that returns the last modified time:
blob.FetchAttributes();
var lastModifiedTime = blob.Properties.LastModifiedUtc;
FetchAttributes is the StorageClient library
equivalent of HEAD. It returns
all the properties and custom metadata of the BLOB, without downloading
the actual file. Table 1 lists the BLOB properties and their
descriptions.
Table 1. BLOB properties
Property name | Description |
---|
BlobType | PageBlob, BlockBlob |
CacheControl | Allows
you to instruct the browser on how to cache the BLOB |
ContentEncoding | Encoding of the header |
ContentLanguage | Language header of the
BLOB |
ContentMD5 | MD5 hash of the content header |
ContentType | The MIME type of the
BLOB |
Etag | Unique identifier of the request
(changes every time a BLOB is modified) |
LastModifiedTimeUtc | Last
time the BLOB was modified |
LeaseStatus | Used with page blocks: Locked,
Unlocked; not available in the
StorageClient library. |
Length | Size of the BLOB, in
bytes |
Now that you’re
familiar with BLOB properties and how to retrieve them without
downloading the file, let’s look at how you can use this knowledge to
improve the performance of your handler.