January 13, 2012 at 11:24 AM

This blog post contains some guidelines for consuming web services, with a focus on exception handling.  We will both handle pure messaging scenario and web service calls from within an orchestration.  I also make a distinguishment between asynchronous and synchronous flows.  Synchronous means that the flow needs to return a message to the original caller.  So in case of troubles, a SoapFault needs to be returned to the calling application.  In an asynchronous flow, you just need to make sure that your web service call is resumable. 

 

Messaging Scenario – Asynchronous

When an error occurs during the web service call, the default behavior of BizTalk retry 3 times and will suspend the request message on the BizTalk Send Port and this instance will be resumable.  This is the perfect behavior for this asynchronous process.

 

Messaging Scenario - Synchronous

If you are in a synchronous process, a suspended Send Port will lead to a timeout on your Receive Port.  In this scenario you need to enable "Propagate Fault Message" on the Send Port and a SoapFault will be returned to the original caller.  Also think about the Retry Count and Retry Interval settings, because a bad configuration can also lead to timeouts.

image

 

Orchestration - Asynchronous

When you consume a web service from within an orchestration, it's getting more complex.  If the consumed web service throws an exception, BizTalk creates by default 2 suspended service instances.  Resuming them does not always have the expected behavior.

 

-  The Orchestration is suspended.  A resume will not change anything to the state of the Orchestration.
-  The Send Port is suspended.  A resume will resume the web service call as expected, but the Orchestration will not be able to continue processing afterwards.

 

image

How can we now achieve a resumable web service call?

 

First of all enable "Propagate Fault Message" on the Send Port.


Also modify the calling orchestration:

-  You need to create a loop.  This loop continues as long as the Boolean bSuccess equals false.

-  Modify the logical Orchestration Send Port and add a Fault Message.  To keep it general, you can choose the SoapFault (which is part of the Microsoft.BizTalk.GlobalPropertySchemas).

clip_image002        clip_image003

-  Add an exception handler to the web service call. Catch the Fault Message that was returned.  Add a suspend shape for human intervention. Note that it’s a good practice to also add an extra exception handler which catches a System.Exception.

-  If the web service call fails: set bSuccess == false in the exception handler.  If the call succeeds, set bSuccess == true, so the orchestration will exit the loop.

 

The result should look like this:

image

 

Now we've created a resumable web service call from within an orchestration.  When testing the orchestration in a failure scenario, you will see that there are still two suspended service instances:

-  The Orchestration is suspended.  This is the one that we've made resumable.

-  The Send Port is suspended.  To avoid this second service instance to be suspended, you can enable "Routing for Failed Messages".  This will generate an ErrorReport, instead of suspending the Send Port.  Subscribe on the ErrorReport with the filter ErrorReport.ErrorType == “FailedMessage”.

 

clip_image006

 

Orchestration - Synchronous

In this scenario, you will also need to catch the SoapFault (or other exception) and make sure that you don’t end up with suspended send port instances. See “Orchestration – Asynchronous”


The extra functionality that you’ll need to add is returning a SoapFault to the original caller.

- Add a Fault Message to the Request/Response receive port of your orchestration.

- You can choose to return a typed Fault or, to keep it general, a SoapFault (which is part of the Microsoft.BizTalk.GlobalPropertySchemas).

- Make sure you return the catched SoapFault (or the created SoapFault in case of other exception) in case of errors.

- Remark that you’ll need to add a decide shape to determine you’re in a success/failure scenario. Otherwise, the compiler will fail (complaining about unconstructed messages).

 

clip_image002[4]

 

Again, think about the Retry Count and Retry Interval settings on the send port.

 

Toon Vanhoutte

Posted in: BizTalk | SOA | WCF

Tags: , ,


January 6, 2012 at 12:25 PM

Recently, we've encountered some problems with SCOM 2007 R2 monitoring of a BizTalk 2010 environment. The SQL Agent Job "Backup BizTalk Server (BizTalkMgmtDb)" failed, but we didn’t receive any SCOM alert about that.  The first reflex was to look at the BizTalk Management Pack.

 

BizTalk Server Management Pack

The BizTalk Server Management Pack contains a rule, called “CRITICAL ERROR: A SQL Server agent job failed - Backup BizTalk Server”, which is responsible for alerting us in case of troubles.  The rule is disabled by default, but we had already enabled the rule with an override.

 

Why didn’t we receive an alert?  We had a closer look at the default rule and discovered that this is the way of identifying the backup job failure:

-    It’s a rule that subscribes on the event log [TypeID="Windows!Microsoft.Windows.EventProvider"]
-    It looks for event log entries with ID = 208 [EventDisplayNumber equals 208] in the Application log
-    The computer name is set to $Target/Property[Type="Microsoft.BizTalk.Server.2010.ServerRole"]/ComputerName$

 

When the error occurred, we indeed discovered event log entries with ID 208 on the SQL server.  But this rule is subscribing on the event log of the BizTalk server.  Conclusion: the default rule will only work on a single box installation (SQL server and BizTalk server have the same event log).

 

To solve this issue, we’ve created a custom rule, based on the default one.  The custom rule had exactly the same configuration, except for the computer name that we’ve changed to:
-    “$Target/Property[Type="Microsoft.BizTalk.Server.2010.BizTalkGroup"]/MgmtDbServerName$”

Now the rule was subscribing on the event log of the SQL Server (running the ManagementDb), and we received an alert when the backup job failed.  This worked fine, until we deployed this rule against a multi-server BizTalk environment, containing a SQL Server cluster.  Suddenly we’ve received SCOM errors, complaining that the SCOM Agent couldn’t access the event log of the MgmtDbServer.  The cause of this is that the BizTalk Management Pack actually discovers the virtual SQL Server Cluster name.  As this is not a physical server name, it’s normal that the SCOM Agent can’t access the event log.

 

To overcome this issue, we could have created a new custom rule, which uses the discovered MgmtDbServer and performs a query on the [msdb].[dbo].[sysjobhistory] system table.  The sysjob tables contain all needed information to detect SQL Agent Job failures.  As this is too complex, we decided to have a look at the SQL Server Management Pack.

 

SQL Server Management Pack

As it is actually a SQL process that fails, the SQL Server Management Pack should be responsible for alerting us.  But why didn’t that happen?  There are actually two reasons for this:

-    The discovery of SQL Agent Jobs is disabled by default.
-    The alerting for SQL Agent Job Failures is disabled by default.

We enabled the discovery and alerting, tested the solution and everything went smooth.

 

Conclusion

SQL Agent Jobs should be monitored by the SQL Server Management Pack.  This Management Pack should always be installed in a BizTalk environment, as SQL Server is the core of BizTalk.  Please, keep in mind that the alerting of SQL Agent Jobs is disabled by default.

 

It’s actually a strange approach of Microsoft to try to include the monitoring of the SQL Agent Jobs in the BizTalk Server Management Pack.  Certainly because the default implementation only works for a single box installation.  On MSDN you can find a vague description on this subject.

Toon Vanhoutte


December 20, 2011 at 6:51 AM

From private to public CTP

Last weekend, a new big step was set for companies in the Microsoft integration space, since the Microsoft Azure team released the first public CTP of the ServiceBus EAI & EDI Labs SDK.  This was formally known as Integration Services.  In september, we got a chance to play with a private CTP of this Azure component and since then we have provided a lot of feedback, some of which has already been taken up in the current release.  The current release seems much more stable and the installation experience was great.  (I installed the CTP on various machines, without a hickup)

It wasn’t surprising to see the BizTalk community picking up this CTP and start trying out various typical BizTalk scenarios in the cloud:

  • Rick Garibay discussed the various components in his blog post.
  • Kent Weare posted two articles (introduction & mapper) on his blog.
  • Mikael Håkansson showed the content based routing capabilities in this article.
  • Steef-Jan Wiggers added an overview TechNet wiki.
  • Harish Agarwal wrote an overview on EAI bridges.

Multi-tenancy & high-density

A huge difference for this model is that our pipelines, mappings and message flows are running on shared resources in the Windows Azure data center in some kind of high-density / multi-tenant container.  This introduces an entire new architecture and concept for isolation.  That also seems like the main reason why following capabilities are not yet possible or available:

  • It is not possible (yet) to develop custom pipeline components and have them running in the Azure runtime.
  • The mapper does not support (yet) custom XSLT or Scripting functoids.
  • Message flow does not contain workflow or custom endpoints.

This is feedback that the Microsoft team has received and is well aware of.  Things just get more complex and risky, when running custom applications or components in a shared environment.  You don’t want my memory leak causing a downgrade, or even failure, in your processes, right?  Based on feedback I gave on the connect web site, I really have the feeling these items will be available over time, so being patient will be important here.

The various components

This CTP contains a nice set of components:

Service Bus Connect

Service Bus Connect introduces an on premises service that exposes local LOB applications (like SAP, SQL, Oracle…) over the Service Bus Relay to the cloud.  This is a more lightweight service, compared with BizTalk and gives customers the ability to have a more lightweight and cheaper solution than buying BizTalk Server for the LOB connectivity.  It also make sure we no longer have to write custom services, or even worse: console applications to expose LOB adapter services over the Service Bus.

Service Bus Connect leverages the LOB Adapter SDK and the available adapters and exposes these endpoints over the Relay services of the Service Bus.  The local endpoints are hosted in Windows Server AppFabric and we can manage these endpoints in various ways:

  • In Visual Studio Server Explorer (ServiceBus Connect Servers).  This makes me think back about the BizTalkExplorer in Visual Studio that took 2 or 3 releases to disappear.  Admins still want MMC, in my opinion.
  • Over a management service, exposed as a WCF service.  One of the things that we want to do for our Codit  Integration Cloud, is exposing this management service over the service bus, so that we can maintain and operate the on premises services from our Cloud management portal.
  • Through powershell

EDI processing

It took Microsoft 5 releases of BizTalk Server, until they provided a full fledged EDI solution in BizTalk Server.  Therefore, it’s great to see these capabilities are already available in this release, because EDI is not disappearing and doesn’t seem to disappear any time soon, how much we all would like it to...  Support for X12 is available and also for AS/2 (the exchange protocol).  What is missing for us, Europeans, is EDIFACT.  Again, some patience will be rewarded over time.  What is very promising for migration or hybrid scenarios, is the fact that the provided EDI/X12 schemas look the same as those that were provided with BizTalk Server.  That will make migration and exchange of these messages from Cloud to On premises BizTalk much easier.

The EDI Trading Management portal allows to define partners and agreements, linked with various messaging entities on the service bus.  All of this is provided through a nice and friendly metro-style UI (what else).

I believe this is one of the most suitable scenarios for cloud integration.  B2B connectivity has been very expensive for years, because of the big EDI Value Added Networks and this is, after AS/2, a new step forward in making things cheaper and more manageable. 

EAI processing

One of the strengths and differentiators of BizTalk towards its competition was that it was one generic suite of components that could be used for both EAI, B2B and ESB solutions.  One products, one tool set, one deployment model.  That’s why it worried me a little to see that EDI and EAI are being seen as two totally different things in the release.  Looking a litle deeper shows that the EDI portal is mainly configuration of partners and endpoints, in order to link messages to the right Service Bus or messaging entities.  Still I think the same portal concepts can become valid for non-EDI integration, where companies just exchange messages in different formats (flat file, XML…) over various protocols (mail, file, FTP, AS/2).  I hope to see that we will be able to configure all of these connections in the same and consistent way.

Looking at the EAI capabilities, there are some nice new and refreshed items available:

  • Mapper: this looks like the BizTalk mapper, but is much different.  One of the biggest differences is that it does not create or support XSLT, or it does not support custom code. 
  • XML Bridges: these are the new pipelines.  A bridge is a head in front of the service bus that is exposed as an endpoint.  Various options are available and are discussed in the posts, mentioned above.  The biggest missing link here, is the extensibility with custom components.  At this moment, it doesn’t look possible to have (de)batching, custom validation, zipping and all these other things we do in BizTalk pipeline components.
    • Another thing that is interesting that a new concept of pub/sub is introduced here.  You can use filters in the message flows and those filters are applied in memory and the first matching filter will make sure the incoming request gets routed to the right endpoint.  The pub/sub here is in memory and is not durable.  Making it durable, requires to have it routed to either a queue or topic.  So, this routing model looks much similar to the WCF Routing service and less to the durable BizTalk or Service Bus topics.

Conclusion

This release is much more stable than the private CTP and looks promising.  To be able to deliver real world integration projects with this, there is still a lot of things needed towards customization and extensibility and towards management and monitoring.  The components are also targeted to real technical/developer oriented people.  With Codit Integration Cloud, we provide the level of abstraction, monitoring and extensibility, while using these EDI & EAI capabilities under the hood.

Sam Vanhoutte

Posted in: Azure | Service Bus | WCF | EDI/AS2

Tags:


November 30, 2011 at 11:15 AM

Host Integration Server 2010 comes with a BizTalk data conversion pipeline component.  This enables the copybook parsing functionality, withou the usage of the HostApps adapters. Great stuff when you need to parse copybook files while using a custom WCF binding for the mainframe connectivity.

 

During a POC, we were glad to discover that the import of a copybook definition goes a lot smoother than in the previous HIS versions.  The copybook definition import results in a HIS data conversion assembly.  This assembly contains the logic to parse the copybook file to XML and vice versa.  We configured the by default installed HIS send pipeline, “DataConversionSendPipeline”, with the generated HIS data conversion assembly and everything went fine. 

 

Afterwards, we’ve changed the POC scenario and needed to add some extra functionality to the send pipeline.  Therefore we’ve created a custom send pipeline and configured it with the HIS data conversion pipeline component.  This custom pipeline had actually the same setup and configuration of the by default installed HIS send pipeline, “DataConversionSendPipeline”.  However we’ve encountered suddenly a bunch of conversion errors. 

 

After many hours of troubleshooting, Sam discovered the following pipeline name dependency in the data conversion pipeline component via Reflector:

 

if (pc.PipelineName.IndexOf("DataConversionSendPipeline") != -1)

{ this._toHost = true; }

else

{ this._toHost = false; }

 

The _toHost property is actually used to determine if the component needs to execute receive pipeline conversion functionality (FF to XML) or send pipeline conversion logic (XML to FF).  The value of this property is set, depending on the name of the send pipeline it belongs to.  A dependency between a pipeline component and a pipeline name is NOT a good practice.  So if you want the component to work correctly in a custom send pipeline, the pipeline name should contain “DataConversionSendPipeline”.  It would be more straightforward to set the _toHost property in the component, depending on the determined pipeline stage at runtime. 

 

We’ve raised this bug via Microsoft Support and we hope to see a fix in the next cumulative update pack.

Posted in:

Tags:


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.


August 4, 2011 at 1:39 PM

In some cases, other applications want to make use of the flat file parsing functionality of BizTalk. These applications need for example a conversion between their .NET object and a flat file, or vice versa. The functional context can be EDI, HL7, Copybook or custom flat file parsing.

The most performant way to expose this BizTalk pipeline functionality as a two-way WCF service, is by routing the transformed request message automatically back to the send pipeline of the two-way receive port. This pure messaging scenario only involves one pub/sub mechanism to the MsgBox.  We have tested this on a single box development machine, arriving at only 60ms roundtrips for our flat file test schema.

This can be achieved by adding a custom pipeline component at the end of the receive pipeline. This pipeline component promotes the necessary properties to route back the request directly to the subscribing send pipeline. The Execute method of this component is where the magic happens:

string ns = http://schemas.microsoft.com/BizTalk/2003/system-properties;

inmsg.Context.Promote("RouteDirectToTP", ns, inmsg.Context.Read("IsRequestResponse", ns));
inmsg.Context.Promote("EpmRRCorrelationToken", ns, inmsg.Context.Read("EpmRRCorrelationToken", ns));

return inmsg;

This logic can also be used in custom disassembler pipeline components, which need to generate a response message that needs to be routed back to the original caller.

Toon Vanhoutte

Posted in:

Tags:


June 5, 2011 at 11:19 PM

In the recent CTP of Windows Azure AppFabric, we can see a lot of new rich-messaging features.  In my previous blog post, I blogged about the publish-subscribe features.  Another interesting feature is the use of sessions when sending messages to a queue.  And that’s what this post is about.

We will demonstrate how to send large messages in an atomic batch of chunks over a queue.

The new queues

The new AppFabric Service Bus queues are much richer in functionality and features than the V1-message buffers or the Windows Azure storage queues.  A list of the biggest differences:

  • Reliable & durable storage (no limit on the TTL-time to live).
  • The maximum size of a queue is 1GB. (100Mb in the CTP version).
  • A message can measure up to 256KB.
  • Different messaging API’s are available: REST, .NET client and WCF bindings.
  • Transactional support in sending messages to a queue.
  • De-duplication of messages.
  • Deferring of messages.

As you can see, the limit of a message size is 256Kb, which is much more than the storage queue limit, but can still be not enough in certain cases.  And that is where sessions come in the picture.

Session concept

The concept of sessions allows receiving messages that belong to a certain logical group all by the same receiver.  This is done by specifying a SessionId on a message.  Receivers can listen on a specific session, or can lock the session for their usage on a first come first served basis.

Sessions can also be used to implement Request-Reply patterns over a queue.  But more on that can be expected in a future blog post.

 

Creating a session-enabled queue

By default, queues are created session-less.  The usage of sessions can only be used on queues that have session-support enabled.  The following code extract shows how to create a queue with sessions enabled.  (notice the usage of the ServiceBusNamespaceClient object.  This is the object you’ll always use in administrative operations.

sbClient.CreateQueue("qName", new QueueDescription { RequiresSession = true });

In this way, the queue will now be created and be able to handle sessions.

 

Sending messages to the queue

The only specific thing that is needed to send messages in a session to a queue, is to define the SessionId property on the specific message.  In this case, I also write a value to the message properties to indicate that the last message of a session is being sent.

var message = BrokeredMessage.CreateMessage(msgContent);
message.SessionId = "MySessionId"; 
message.MessageId = "MyMessageId"; 
if (isLastMessage) { message.Properties["LastMessageInSession"] = true; }

 

Receiving messages from a session

The specific thing on receiving messages in a session, is to use a SessionReceiver.  This receiver will make sure that all messages it receives will belong to the same session.  It is possible to listen on a specific session (by passing in the session name) and to specify a session timeout.

QueueClient queueClient = msgFactory.CreateQueueClient("LargeFileQueue");
SessionReceiver sessionReceiver = queueClient.AcceptSessionReceiver();
while (sessionReceiver.TryReceive(TimeSpan.FromSeconds(10), out receivedMessage))
{
	Console.WriteLine("Message received in session " + receivedMessage.SessionId);
	if (receivedMessage.Properties.ContainsKey("LastMessageInSession"))
	{     
		Console.WriteLine("Last message of session received");
		break; 
	} 
}

In the above mentioned sample, I am looping until I receive the ‘last message in the session’.

The sample Sending large messages in chunks to a session

In the sample that I upload, I send large messages in chunks to a session-enable queue.  Using multiple receivers, I am guaranteed that each file will only be received by exactly one receiver.

 

Functionality

The sample contains a sender where you can specify a directory where all messages in that directory will be picked up and submitted (in parallel) to a session-enabled queue, if the checkbox is checked.  Otherwise they will be sent to a session-less queue. (to demonstrate that messages will be received in random order).

The receiver is a console app that listens for incoming messages based on the session.  You can startup multiple receivers, to indicate that each receiver will receive messages to its own session.

sessioncapture

These are the most important design steps I took:

 

Sending messages

  • In the sample, I am using a Parallel.ForEach to loop over a bunch of files and send them in parallel.  This way, I am sure that messages won’t arrive in sequence on the queue.
  • Each large message is being sent in a transaction to the queue. 
  • On every message, I use the file name as the session id.
  • On the last message in the batch, I write the ‘LastMessageInSession’ property to make this visible to the receiver.

Receiving messages

  • I am using the PeekLock receive method to make sure I only remove the messages from the queue, when the full session has been received.
  • I receive the messages in a TransactionScope.  This makes sure that the session on itself is being rollbacked, in case of an exception.

The code of this sample can be found here.

Conclusions

This post was a new example of another great messaging feature that comes with the AppFabric Service Bus Enhancements.  We explored the sessions to group messages to the same receiver.  This scenario in this post demonstrated that we can split large messages in smaller chunks but still are able to handle them in one atomic batch.

Sam Vanhoutte

Posted in: AppFabric | Azure | Service Bus

Tags:


June 3, 2011 at 9:08 AM

Richard Seroter, recognized blogger, BizTalk MVP and book author, has a series of interviews with people in the “connected technology” space. Yesterday, he published its 31st interview, with me.

If you want to know more about the way we see the AppFabric Service Bus positioned and used, I definitely recommend you to have a look at it. And make sure to subscribe to the blog of Richard too; you won’t regret it.

Here it is: http://seroter.wordpress.com/2011/06/02/interview-series-four-questions-with-sam-vanhoutte/

Sam Vanhoutte

Posted in: AppFabric | Azure | BizTalk

Tags: