Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Παρουσίαση με Ετικέτες

Όλες οι Ετικέτε... » Architecture   (RSS)
Continuing on where I left it on my previous post, I’m going to explain how the Announcement service works and why we choose that approach. The way JBoss and mod_proxy work now is that every time something changes in the topology, either a new proxy is added or removed or a JBoss node, then the proxy [...]
0 σχόλια
Δημοσίευση στην κατηγορία: , , , ,


Recently, I’ve been looking a way to persist the status of an idling Workflow on WF4. There is a way to use SQL Azure to achieve this, after modifying the scripts because they contain unsupported T-SQL commands, but it’s totally an overkill to use it just to persist WF information, if you’re not using the RDBMS for another reason.

I decided to modify the FilePersistence.cs of the Custom Persistence Service sample in WF 4 Samples Library and make it work with Windows Azure Blob storage. I’ve created two new methods to Serialize and Deserialize information to/from Blob storage.

Here is some code:

   1: private void SerialiazeToAzureStorage(byte[] workflowBytes, Guid id)
   2:      {
   3:          var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
   4:          var container = account.CreateCloudBlobClient().GetContainerReference("workflow_persistence");
   5:  
   6:          var blob = container.GetBlobReference(id.ToString());
   7:          
   8:          blob.Properties.ContentType = "application/octet-stream";
   9:          using (var stream = new MemoryStream())
  10:          {
  11:              stream.Read(workflowBytes, 0, workflowBytes.Length);
  12:              blob.UploadFromStream(stream);
  13:          }
  14:      }
  15:  
  16:      private byte[] DeserialiazeFromAzureStorage(Guid id)
  17:      {
  18:          var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
  19:          var container = account.CreateCloudBlobClient().GetContainerReference("workflow_persistence");
  20:  
  21:          var blob = container.GetBlobReference(id.ToString());
  22:  
  23:          return blob.DownloadByteArray();
  24:      }

Just make sure you’ve created “workflow_persistence” blob container before using these methods.

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


Paspartu is French for “one size fits all”. Recently I’ve been coming across posts explaining and “promoting” the idea of spawning threads inside a worker role each one of them with a unique work to be done. All are sharing the same idea and all of them are describing the same thing.

The idea

You have some work to do, but you want to do it with the most efficient way, without having underutilized resources, which is one of the benefits of cloud computing anyway.

The implementation

You have a worker process (Worker Role on Windows Azure) which processes some data. Certainly that’s a good implementation but it’s not a best practice. Most of the time, your instance will be underutilized, unless your doing some CPU and memory intensive work and you have a continuous flow of data to be processed.

In another implementation, we created a Master-Slave pattern. A master distributes work to other slave worker roles, roles are picking up their work, do their stuff, return result and start over again. Still, in some cases that’s not the best idea either. Same cons as before. Underutilized resources, high risk of failure. If the master dies, unless properly designed, your system dies. You can’t process any data.

So, another one appeared. Inside a worker role, spawn multiple threads, running their own processes or methods, doing their work and return result. Underutilization is minimized, Thread Pool is doing all the hard work for us and as soon as .NET 4.0 is supported on Windows Azure, parallelization is easy and, allow me to say, mandatory. But what happens if the worker instance dies? Or restarts? Yes, your guess is correct. You lose all threads and all the processing done by that moment, is lost, unless you persist it somehow. If you had multiple instances of your worker role to imitate that behavior, that wouldn’t happen. You’ll only lose data from the instance that died.

As Eugenio Pace says “You have to be prepared to fail” and he’s right. Every single moment, your instance can die, without a single notice and you have to be prepared to deal with it.

Oh, boy.

So really, there is no single solution or best practice. For me, it’s best guidance. Depending on your scenario, one of the solutions above or even a new one, can fit better for you than for others. Every project is unique and has to be treated as such. Try to think out of the box and remember that this is deep water for everyone. It is just some of us swim better..

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


When you have your service running on Windows Azure, the least thing you want is monitoring every now and then and decide if there is a necessity for specific actions based on your monitoring data. You want the service to be, in some degree, self-manageable and decide on its own what the necessary actions should take place to satisfy a monitoring alert. In this post, I’m not going to use Service Management API to increase or decrease the number of instances, instead I’m going to log a warning, but in a future post I’m going to use it in combination with this logging message, so consider this as a series of posts with this being the first one.

The most common scenario is dynamically increase or decrease VM instances to be able to process more messages as our Queues are getting filled up. You have to create your own “logic”, a decision mechanism if you like, which will execute some steps and bring the service to a state that satisfies your condition because there is no out-of-the-box solution from Windows Azure. A number of companies have announced that their monitoring/health software is going to support Windows Azure. You can find more information about that if you search the internet, or visit the Windows Azure Portal under Partners section.

In the code below I’m monitoring the messages inside a Queue at every role cycle:

   1: CloudQueue cloudQueue = cloudQueueClient.GetQueueReference("calculateP");
   2:  
   3: cloudQueue.CreateIfNotExist();
   4: cloudQueue.FetchAttributes();
   5:  
   6: /* Call this method to calculate your WorkLoad */
   7: CalculateWorkLoad(cloudQueue.ApproximateMessageCount);

and this is the code inside CalculateWorkLoad:

   1: public void CalculateWorkLoad(int? messages)
   2: {
   3:   /* If there are messages, find the average of messages 
   4:      available every X seconds
   5:   X = the ThreadSleep time, in my case every 5 seconds */
   6:   if (messages != null)
   7:    average = messages.Value / (threadsleep / 1000);
   8:  
   9:   DecideIncDecOfInstances(average);
  10: }

Note that if you want to get accurate values on queue’s properties, you have to call FetchAttributes();

There is nothing fancy in my code I’m just finding an average workload (number of messages in my Queue) every 5 seconds and I’m passing this value at DecideIncDecOfInstances(). Here is the code:

   1: public void DecideIncDecOfInstances(int average)
   2: {
   3:     int instances = 2;
   4:  
   5:     /* If my average is above 1000 */
   6:     if (average > 1000)
   7:         OneForEveryThousand(average, ref instances);
   8:         WarnWeNeedMoreVM(instances);
   9: }

OneForEveryThousand count is actually increasing the default number of instances, which is two (2), by one (1) for every thousand (1000) messages in Queue’s average count.

This is the final part of my code, WarnWeNeedMoreVM which logs our need for more or less VM’s.

   1: public void WarnWeNeedMoreVM(int instances)
   2: {
   3:     if (instances == 2) return;
   4:  
   5:     Trace.WriteLine(String.Format("WARNING: Instances Count should be {0} on this {1} Role!", 
   6:                    instances, RoleEnvironment.CurrentRoleInstance.Role.Name), "Information");
   7: }

In my next post for this series, I’m going to use the newly released Service Management API to upload a new configuration file which increases or decreases the number of VM instances in my role(s) dynamically. Stay tunned!

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


In general, there are two kind of updates you’ll mainly perform on Windows Azure. One of them is changing your application’s logic (or so called business logic) e.g. the way you handle/read queues, or how you process data or even protocol updates etc and the other is schema updates/changes. I’m not referring to SQL Azure schema changes, which is a different scenario and approach but in Table storage schema changes and to be more precise only on specific entity types because, as you already now, Table storage is schema-less. As in In-Place upgrades, the same logic applies here too. Introduce a hybrid version, which handles both the new and the old version of your entity (newly introduced properties) and then proceed to your “final” version which handles the new version of your entities (and properties) only. It’s a very easy technique and I’m explaining how to add new properties and of course remove although it’s a less likely scenario.

During my presentation at Microsoft DevDays “Make Web not War”, I’ve created an example using a Weather service and an entity called WeatherEntry, so let’s use it. My class looks like this:

   1: [DataServiceKey("PartitionKey","RowKey")]
   2: public class WeatherEntry : TableServiceEntity
   3: {
   4:     public WeatherEntry()
   5:     {
   6:         PartitionKey = "athgr";
   7:         RowKey = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - DateTime.Now.Ticks, Guid.NewGuid());
   8:     }
   9:     public DateTime TimeOfCapture{ get; set; }
  10:     public string Temperature{ get; set; }
  11: }

There is nothing special at this class. I use two custom properties, TimeOfCapture and Temperature and I’m going to make small change and I’ll add “SchemaVersion” which is needed to achieve the functionality I want. When I want to create a new entry, all I do now is instantiate a WeatherEntry, set the values and use a helper method called AddEntry to persist my changes.

   1: public void AddEntry(string temperature, DateTime timeofc)
   2: {
   3:    this.AddObject("WeatherData", new WeatherEntry { TimeOfCapture = timeofc, Temperature = temperature, SchemaVersion = "1.0" });
   4:    this.SaveChanges();
   5: }

I’m using TableServiceContext from the newly released StorageClient and methods like UpdateObject, DeleteObject, AddObject etc, exist in my data service context where AddEntry helper method relies. At the moment my Table schema looks like this:

schema-before-change  

It’s pretty obvious there is no special handling during saving of my entities but this is about to change in my hybrid version.

The hybrid

I did some changes at my base class and I’ve added a new property. It’s holding the temperature sample area, in my case Spata where Athens International Airport is.

My class looks like this now:

   1: [DataServiceKey("PartitionKey","RowKey")]
   2: public class WeatherEntry : TableServiceEntity
   3: {
   4:     public WeatherEntry()
   5:     {
   6:         PartitionKey = "athgr";
   7:         RowKey = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - DateTime.Now.Ticks, Guid.NewGuid());
   8:     }
   9:     public DateTime TimeOfCapture{ get; set; }
  10:     public string Temperature{ get; set; }
  11:     public string SampleArea{ get; set; }
  12:     public string SchemaVersion{ get; set;}
  13: }

So, this hybrid client has somehow to handle entities from version 1 and entities from version 2 because my schema is already on version 2. How do you do that? The main idea is that you retrieve an entity from table storage and you check if SampleArea and SchemaVersion have a value. If they don’t, put a default value and save them. In my case my schema version number has to be 1.5 as this is the default schema number for this hybrid solution. One key point to this procedure is before you upgrade your client to this hybrid, you roll-out an update enabling “IgnoreMissingProperties” flag on your TableServiceContext. If IgnoreMissingProperties is true, when a version 1 client is trying to access your entities which are on version 2 and have those new properties, it WON’T raise an exception and it will just ignore them.

   1: var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
   2: var context = new WeatherServiceContext(account.TableEndpoint.ToString(), account.Credentials);
   3:  
   4: /* Ignore missing properties on my entities */
   5: context.IgnoreMissingProperties = true;

Remember, you have to roll-out an update BEFORE you upgrade to this hybrid.

Whenever I’m updating an entity to Table Storage, I’m checking its version Schema and if it’s not “1.5” I update it and put a default value on SampleArea:

   1: public void UpdateEntry(WeatherEntry wEntry)
   2: {
   3:     if (wEntry.SchemaVersion.Equals("1.0"))
   4:     {
   5:         /* If schema version is 1.0, update it to 1.5 
   6:          * and set a default value on SampleArea */
   7:         wEntry.SchemaVersion = "1.5";
   8:         wEntry.SampleArea = "Spata";
   9:     }
  10:     /* Put some try catch here to 
  11:      * catch concurrency exceptions */
  12:     this.UpdateObject(wEntry);
  13:     this.SaveChanges();
  14: }

My schema now looks like this. Notice that both versions of my entities co-exist and are handled just fine by my application.

schema-after-change

Upgrading to version 2.0

Upgrading to version 2.0 is now easy. All you have to do is change the default schema number when you create a new entity to version 2.0 and of course update your “UpdateEntry” helper method to check if version is 1.5 and update the value to 2.0.

   1: this.AddObject("WeatherData", new WeatherEntry { TimeOfCapture = timeofc, Temperature = temperature, SchemaVersion = "2.0" });

and

   1: public void UpdateEntry(WeatherEntry wEntry)
   2: {
   3:    if (wEntry.SchemaVersion.Equals("1.5"))
   4:    {
   5:        /* If schema is version 1.5 it already has a default
   6:         value, all we have to do is update schema version so 
   7:         our system won't ignore the default value */
   8:        wEntry.SchemaVersion = "2.0";
   9:    }
  10:    /* Put some try catch here to 
  11:     * catch concurrency exceptions */
  12:    this.UpdateObject(wEntry);
  13:    this.SaveChanges();
  14: }

Whenever you retrieve a value from Table Storage, you have to check if it’s on version 2.0. If it is, you can safely use its SampleArea value which is not the default any more. That’s because schema version is changed when you actually call “UpdateEntry” which means you had the chance to change SampleArea to a non-default value. But if it’s on version 1.5 you have to ignore it or update it to a new, correct value.

If you do want to use the default value anyway, you can create a temporary worker role which will scan the whole table and update all of your schema version numbers to 2.0.

How about when you remove properties

That’s a really easy modification. If you remove a property, you can use a SaveChangesOption called ReplaceOnUpdate during SaveChanges() which will override your entity with the new schema. Don’t forget to update your schema version number to something unique and put some checks into your application to avoid failures when trying to read non-existent properties due to newer schema version.

   1: this.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);


That’s all for today! Smile

P.K

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


In a previous post I’ve described what a VIP Swap is and how you can use it as an updating method to avoid service disruption. This particular method doesn’t apply to all possible scenarios and if not always, most of the times, during protocol updates or schema changes you’ll need to upgrade your service when its still running, chunk-by-chunk and without any downtime or disruption. By In-Place, I mean upgrades that take place during which both versions (old version and new version) are running side-by-side. In order to better understand the process below, you should read my “Upgrade domains” post in which there is a detailed description of what Upgrade domains are, how they affect your application, how you can configure the number of domains etc.

To avoid service disruption and outage Windows Azure is upgrading your application domain per domain (upgrade domain that is). That will result in a particular state where your Upgrade Domain 0 (UD0) is running a newer version of your client/service/what_have_you and your UD1, UD2 etc will run an older version. The best approach is to have a two-step phase upgrade.

Let’s call our old protocol version V1 and our new version V2. At this point, you should consider introducing a new client version called 1.5 which is a hybrid. What this version does is understanding both protocols used in both versions but always use protocol V1 by default and only respond by protocol V2 if they request is on V2. You can now start pushing your upgrades either by Service Management API or using Windows Azure Developer portal to completely automate the procedure. By the end of this process, you’ll achieve a seamless upgrade to your service without any disruption and all of your clients will upgrade to this hybrid. As soon as your first step is done and all of your domains are running version 1.5, you can proceed to step two (2).

In your second step you’ll be repeating the same process but this time your version 2 clients will use protocol V2 by default. Remember, your 1.5 clients DO understand protocol V2 and they respond to it properly once called upon with. To make it simple, this time you’re deploying version 2 of your client which uses version 2 of your protocol only. Old legacy code for version 1 is removed completely. As your upgrade domains complete the second step you’ll be having all your roles using version 2 of your protocol, again without any service disruption or downtime.

Schema changes have a similar approach but I’ll make a different post and actually put some code on it to demonstrate that behavior.

0 σχόλια
Δημοσίευση στην κατηγορία: , , ,


Windows Azure automatically divides your role instances into some “logical” domains called upgrade domains. During upgrade, Azure is updating these domains one by one. This is a by design behavior to avoid nasty situations. Some of the last feature additions and enhancements on the platform was the ability to notify your role instances in case of “environment” changes, like adding or removing being most common. In such case, all your roles get a notification of this change. Imagine if you had 50 or 60 role instances, getting notified all at once and start doing various actions to react to this change. It will be a complete disaster for your service.

logical-upgrade-domain 
Source: MSDN

The way to address this problem is upgrade domains. As I said, during upgrade Windows Azure updates them one by one and only the associated role instances to a specific domain get notified of the changes taking place. Only a small number of your role instances will get notified, react and the rest will remain intact providing a seamless upgrade experience and no service disruption or downtime.

role-upgrade
Source: MSDN

There is no control on how Windows Azure divides your instances and roles into upgrade domains. It’s a completely automated procedure and it’s being done on the background. There are two ways to perform an upgrade on a domain. Using Service Management API or the Windows Azure Developer portal. On the Developer Portal there are two more options. Automatic and manual. If you select automatic, Windows Azure will upgrade your domains without any hassle about what is going on. If you select manual, you’ll have to upgrade all of your domains one by one.

This is some of the magic provided by Windows Azure operating system and Windows Azure platform to provide scalability, availability and high reliability for your service.

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


Today, during my presentation at Microsoft DevDays “Make Web not War” I had a pretty nice question about concurrency and I left the question somehow blurry and without a straight answer. Sorry, but we were changing subjects so fast that I missed it and I only realized it on my way back.

The answer is yes, there is concurrency. If you examine a record on your table storage you’ll see that there is a Timestamp field or so called “ETag”. Windows Azure is using this field to apply optimistic concurrency on your data. When you retrieve a record from the database, change a value and then call “UpdateObject”, Windows Azure will check if timestamp field has the same value on your object as it does on the table and if it does it will update just fine. If it doesn’t, it means someone else changed it and you’ll get an Exception which you have to handle. One possible solution is retrieve the object again, update your values and push it back. The final approach to concurrency is absolutely up to the developer and varies between different types of applications.

As I mentioned during my presentation, there a lot of different approaches to handle concurrency on Windows Azure Table Storage. There is a very nice video on the “How to” section on MSDN about Windows Azure Table Storage concurrency which can certainly give you some ideas.

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


Performing an in-place upgrade on Windows Azure to change your service definition file it’s not possible unless you stop the service, upgrade and then start it again. Otherwise you can do a VIP Swap. VIP stands for Virtual IP and VIP swaps can be either done by the Developer portal or using the Service Management API by calling “Swap Deployment” method.

If you use VIP Swap and as long as you the endpoints between the old and new service definition are identical, the upgrade process is seamless and pretty straightforward without any service interruption. But if, for example, you introduce a new endpoint or delete and older one, then this process is not possible and you have to stop, upgrade, start.

So, how can you perform this operation from the Developer portal. Simply logon to your account, go to Summary page, open your target project, open the service and then upload the new service definition file on Staging. Now, if you click Run on Staging, both versions of your service will work just fine (one in Production, one in Staging). When you hit the Upgrade button (the one with arrows in the middle) then Azure will upgrade your service from Staging to Production, changing the service definition file and complete the process just fine thus performing a VIP swap in the background.

You can perform the same operation using Service Management API and “Swap Deployment” method as I mentioned before.

For more information about VIP Swap using Service Management API, go here –> MSDN, Azure Service Management API, VIP Swap

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,


Its been a while since Windows Azure caught the attention of a broader audience rising all kinds of questions from the most simple “How do I access my table storage” to the most complex and generic “How do I optimize my code to pay less”. Although there is a straight answer on the first one, that’s not the case on the second. Designing an application has always been a fairly complex scenario when it comes to high scale enterprise solutions or even on mid-sized businesses.

There are a few things to consider when you’re trying to “migrate” your application to the Azure platform.

You should have in mind that, you literally pay for your mistakes. As long as you’re not a developer account, which by the way you “pay” but in a different way, you are on a pay as you go model for various things, like Transactions, Compute hour, Bandwidth and of course storage. Oh and database size on SQL Azure. So every mistake that you make, let’s say un-optimized code producing more messages/transactions that necessary, you pay for it.

What’s a Compute hour? Well, it’s the number of instances multiplied by “consumed” (service) hours. And what’s a consumed (service) hour? It’s a simple medium size Azure instance having an average of 70% CPU peak, on a 1.60 GHZ CPU with 1.75 GB of RAM and 155 GB of non-persistent data. That means it’s not “uptime” as many of you think it is. So, when it comes to compute hours, you should measure how many hours does your application consume and optimize your code to consume less. Disable any roles, either Worker or Web when you don’t need them, it will cost you less.

SQL Azure as your database server. There are some catches here also. You should consider re-designing and re-writing the parts where your application is using BLOBs, specially when they are big ones, to use Azure table storage. That’s because of two reasons. First, there are only 2 editions of SQL Azure available as of now, 1GB and 10GB database size limit. You can pretty easily hit the limit when you have large amounts of BLOBs (images, documents etc). The second reason is that you don’t take advantage of the Azure CDN (Content Delivery Network) which means all your clients are served by the server(s) hosting your database even if this is slower because of the network latency. If you use Azure CDN , your content is distributed at various key points all around the world (Europe, Asia, USA etc) and your clients are served by the fastest available server nearby their location. And that’s not only that. Azure storage is using REST which means your content is also cached by various proxies increasing the performance even more.

Any thoughts?

PK.

0 σχόλια
Δημοσίευση στην κατηγορία: , ,