October 27, 2011 at 7:29 AM

Great news coming from the Azure AppFabric Service Bus team.  As from today, they have updated the Service Bus to include load balancing in the Relay Service capabilities.  It will now be possible to have up to 25 listeners registered to the same service endpoint.  When a message is then sent to that endpoint, only one of these endpoints will get the service call, based on a random decision on the relay cloud infrastructure.

  • First, we got an e-mail with the announcement through our Azure agreement
  • After that, a tweet of Valery Mizonov (from the AppFabric CAT team) appeared: #ServiceBus relay load balancing was one of your top requirements, dear community. We are done. What’s the next big thing you need?

 

How to enable this functionality.

No update of SDK is needed, everything is included in the AppFabric 1.5 SDK.

The only thing that needs to be done, is change your code to manage the number of concurrent listeners per endpoint and set the limits right. I expect that each of these listeners will count for a billable connection, so the limits are important indeed.

Scale out scenarios

Before this load balancing

Before this capability, a lot of issues were encountered when opening service bus endpoints on multi-instance computers.  In that case, the AddressAlreadyInUseException was thrown.

  • When a Web or Worker role opened a relay connection, but had more than one instance (to be high available), the second instance that tried to open that same endpoint got an exception, because the other instance already registered on it.
  • With BizTalk Server multi-server groups, the receive location with the Relay Binding only could be opened on one host instance.

New scenarios possible

Now it becomes possible to have real scaled out infrastructure and logic on premises too.  Customers who have geo-clustered data centers with redundant applications and logic can now expose that same level of availability to the cloud.

A concrete example

An concrete example of how we can leverage this, is the following. For one of our cloud scenarios, we need to do a lot of flat file parsing.  This we do on an on-premises hosted BizTalk Server.  Therefore, we created a generic web service that accepts the flat file with a message identifier and returns the parsed XML.

Until now, only one server could expose this functionality over the service bus.  But, in case of outage in our on premises data center, we would’ve been offline with this capability, making our entire solution not functioning for that amount of time.  With the new load balancing feature, we just have to expose the same service on a BizTalk Server in another data center (of our hosting partner) and we’re high available just like that.

 

So we can conclude that with this new feature, the following things have been shown:

  • The service bus keeps on being improved to be a world class reliable hybrid connectivity bus.
  • It is great that this feature is introduced, without a new release of SDK being required.  That is the power of the cloud.
  • Most importantly: on premises services can now be scaled better to leverage cloud power on premises too.

 

Sam Vanhoutte

Posted in: AppFabric | Azure | Service Bus

Tags:


October 15, 2011 at 8:58 PM

The BizTalk Sever SDK comes with an interesting Pipeline component sample that allows executing Xsl mapping files in a pipeline.

This functionality can be of interest when the receive port or send port mappings are not executed at the desired time! Receive port mappings are executed after the pipeline execution, send port mappings are executed before the pipeline execution. Thanks to this pipeline component you get control over the exact time when a transformation gets executed.

Although this functionality can be very useful the code of this sample contains some problems that need fixing before using this in production environments.

Let’s take a look at the business end of the sample, the TransformMessage method (you can find the original sample code in this location: <BizTalk installation directory>\SDK\Samples\Pipelines\XslTransformComponent):

 

private Stream TransformMessage(Stream stm)
{
	 MemoryStream ms = null;
	 string validXsltPath = null;
 
	 try 
	 {
  		// Get the full path to the Xslt file
  		validXsltPath = GetValidXsltPath(xsltPath);
  
  		// Load transform
  		XslTransform transform = new XslTransform();
  		transform.Load(validXsltPath);
    
  		//Load Xml stream in XmlDocument.
  		XmlDocument doc = new XmlDocument();
  		doc.Load(stm);
    
  		//Create memory stream to hold transformed data.
  		ms = new MemoryStream();
   
  		//Preform transform
  		transform.Transform(doc, null, ms, null);
  		ms.Seek(0, SeekOrigin.Begin);
 	}
	catch(Exception e) 
 	{
  		System.Diagnostics.Trace.WriteLine(e.Message);
  		System.Diagnostics.Trace.WriteLine(e.StackTrace);
  		throw e;
	}

 	return ms;
}


The signature of the method accepts a Stream as input parameter and returns a Stream as result. Perfect to keep everything streaming…

Then a XslTransform object is created. At first, this might look like a good idea, but XslTransform will load the message into memory internally! For smaller messages this will not cause any issues but bigger messages will cause a System.OutOfMemoryException…

To get rid of this problem I replaced the XslTransform class with the BTSXslTransform class. This class uses the BizTalk transformation engine. The BizTalk transformation engine will only load small messages into memory and will use disk space if the message size reaches a certain threshold.

 

The following line instantiates the BizTalk mapper engine (add a reference to Microsoft.XLANGs.BaseType)

BTSXslTransform trans = new BTSXslTransform();


Use the following line to execute the transform:

trans.ScalableTransform(inputReader, null, vs, new XmlUrlResolver(), false)

 
The following problem we encounter in the original sample is this section:

XmlDocument doc = new XmlDocument();
doc.Load(stm);

This section reads the stream into memory again via an XmlDocument.
I replace this section with this line:

XmlTextReader inputReader = new XmlTextReader(stm);

Instead of feeding the message to the transform method as one memory chunk, I present it a stream that can be pulled by the BTSXslTransform object.

There is one last thing to change in this sample to make it suitable for large messages:

ms = new MemoryStream();

A MemoryStream is used to store the result of the transform operation. Unfortunately a MemoryStream uses memory to store the stream. This makes it unusable for large messages.

Luckily BizTalk Server comes with a stream class that has the same functionality as MemoryStream but one that uses disk space to store large streams. This class is the VirtualStream class (add a reference to Microsoft.BizTalk.Streaming).

Instantiate a VirtualStream object to hold the result of the transformation:

vs = new VirtualStream(VirtualStream.MemoryFlag.AutoOverFlowToDisk);

The AutoOverFlowToDisk instructs this stream to use disk space for large messages.

 

The changed TransformMessage function now looks like this:

 

private Stream TransformMessage(Stream stm)
{
 	VirtualStream vs = null;
	string validXsltPath = null;
  
 	try 
 	{
  		// Get the full path to the Xslt file
  		validXsltPath = GetValidXsltPath(xsltPath);
  		XmlTextReader stylesheet = new XmlTextReader(validXsltPath);

		// Load transform
		BTSXslTransform trans = new BTSXslTransform();
		trans.Load(stylesheet);

		XmlTextReader inputReader = new XmlTextReader(stm);
                    
  		//Create memory stream to hold transformed data.
  		vs = new VirtualStream(VirtualStream.MemoryFlag.AutoOverFlowToDisk);
                
  		//Preform transform
		trans.ScalableTransform(inputReader, null, vs, new    XmlUrlResolver(), false);
    
  		vs.Seek(0, SeekOrigin.Begin);
 	} 
 	catch(Exception e) 
 	{
  		System.Diagnostics.Trace.WriteLine(e.Message);
  		System.Diagnostics.Trace.WriteLine(e.StackTrace);
  		throw e;
 	}
  	return vs;
}

 

When this code is compiled into a pipeline component, it allows executing large transformation exactly where you want it in the BizTalk pipeline infrastructure. This component will keep memory consumption flat, even when processing very large Xml files.

 

The source code of this article can be downloaded from this post as attachement.

 

XslTransform.zip (30,62 kb)

 

Peter Borremans

Posted in: BizTalk | Performance

Tags:


October 11, 2011 at 10:08 AM

On one of the BizTalk environments hosted by Codit we recently migrated our shared storage. 

The environment contains 2 2-node clusters (for the BizTalk and SQL environment). 

Once the particularities figured out this proved to be a painless process:

 

Preparation

 First we prepared the new storage as we normally would: connect to the new iSCSI Target and prepare the disks. We provided the new partitions with temporary drive letters and added the new storage to the clustered applications.

 

Data Migration

Before migrating the data we took all BizTalk and SQL services down.

With the services offline we copied the data from the old to the new disks. 

To retain permissions data was copied using XCopy:

xcopy source destination /O /X /E /H /K

/E- Copies folders and subfolders, including empty ones. 

/H- Copies hidden and system files also. 

/K- Copies attributes. Typically, Xcopy resets read-only attributes.

/O- Copies file ownership and ACL information.

/X  Copies file audit settings (implies /O).-

 

Note: This is not necessary for the cluster quorum..

 

Cluster Reconfiguration

Moving the quorum disk is painless using the Failover Cluster Management mmc:

 

 Once the quorum is moved we replace the old storage with the new:

Start by giving the old disks (except the quorum disk) a new temporary drive letter. 

 Give the new disks the drive letter of the disk they are replacing.

 In the Failover Cluster mmc, in the properties of the services replace the dependency to the old storage.

 

Clean-up

Delete the old disks from the cluster storage.

Log off from and delete the old portal.

 

We used this procedure on 4 of our clusters without any issues, apart from the downtime. 

The time configuring was limited, most of the time was ‘lost’ copying over the data.