Kapil Chadha

  Home  |   Contact  |   Syndication    |   Login
  7 Posts | 1 Stories | 3 Comments | 0 Trackbacks

News

Twitter












Archives

Documents

Thursday, December 17, 2009 #

Please visit here for the details.


Tuesday, December 08, 2009 #

While working on a typical BizTalk scenario (explained below), I came across a finding (at least for me) which I thought I should share. It can be found here.


Wednesday, November 25, 2009 #

Background:

Out of first few tasks that were assigned to me in my new project, I was asked to help testing team with promoting an existing partially tested BizTalk interface. After little bit of code re-factoring and ensuring that the design has been simplified (removed some unwanted logging etc.), we put code to the test. Functionality wise there were not many issues which surprised us and we quickly got over it. However, it wasn’t for long that we realized that there was some obvious issue hidden somewhere beneath the layers of the code, which ultimately got highlighted during our stress testing of the interface.

Interface Scenario:

Customers make a call into BizTalk - HTTP receive-location hosted under IIS (normal setup). This in turn instantiate an orchestration that makes a call into a backend ERP application (slow in nature) using custom-written socket code. In case of positive response from ERP application it simply maps a result back on to the HTTP response body. In case of an exception; orchestration tries to fetch a custom response configured in one of the custom SQL Server tables and maps this to the body of HTTP response.

(I believe that SQL adapter was not used as the .net code to manage configuration held in SQL Server was presented as a library code and was been used from various other locations of the solution/s)

Crunch Time:

All was going reasonably well while we stressed the interface with the gush of inbound HTTP requests though we felt that it was slightly below our expectations. It was expected performance though. Then we attempted to perform a little bit of negative testing. One of the guys (always happy chap) here, kindly obliged by switching ERP into the mode that started to refuse any request. We thought that this should reduce overall latency time greatly as ERP processing time has simply been discarded out of the equation. To our surprise, interface slowed down heavily, BizTalk started to queue up messages, overall thread usage shot up, spool table started growing (and was very resistant to SQL purge jobs) etc etc..

All this behavior at first came as a shock to us and drove us mad for the good few minutes. I started looking for bottleneck/s. Surprisingly, BizTalk was not throttling, which indicated to me that thresholds haven’t been broken yet. So what the hell was slowing interface down? Well, it soon became obvious when I looked into the HAT and noticed that the call to the .Net code that pulls custom response message back from the custom table was taking horribly long (in the region of 15-20 seconds). That was the first time I looked into that part of the solution and found that the way configuration was interrogated was by using inline “Select” statements which were fired against the SQL Server. No need to say that this style of coding has a major affect on the performance. Anyways, I quickly modified the code by pushing the logic into the stored procedure and do another round of stress testing. The performance gains were astonishing. We gained 80% in performance and all quickly fell in place.

The bit that surprised me was that this is a well known fact in the industry and still we sometimes manage to overlook it and end up paying performance penalties. Good that we picked this up in our test rounds; otherwise on production it could have been really difficult (with lot more and types of interfaces) to isolate the performance bottlenecks.

Therefore, the moral of a story is “Never-ever use inline SQL statements in your .Net code or for that matter any front end production ready application code”.

Ps: One of the reasons that I wrote this blog is; on numerous occasions I have come across situations when people bash BizTalk for all sorts of issues without really understanding the underline design and real bottlenecks in the solutions.

Below are some numbers that backs up the story above:

 

HTTP-Sync message processing benchmarking

 

 

 

 

Inputs

 

 

 

 

 

 

 

 

Number of threads

 

150

 

Submission batch size

 

150

 

Sleep interval between each submission (ms)

 

1

 

Total num of messages

 

600

 

 

 

 

Result

 

 

 

 

 

 

 

 

Old Code (With inline SQL execution)

 

 

 

 

 

 

RA1

Start Time

 

25/11/2009 13:07

RA2

Stop Time

 

 25/11/2009 13:14:28

RA3

Total time taken (seconds)

 

430.9

RA4

Number of messages processed /sec

 

1.4

 

 

 

 

 

 

 

 

 

 

 

 

 

New Code (Using stored procedure)

 

 

 

 

 

 

RB1

Start Time

 

25/11/2009 13:19

RB2

Stop Time

 

25/11/2009 13:21

RB3

Total time taken (seconds)

 

80.85

RB4

Number of messages processed /sec

 

7.42

       
       
 

Performance gain (secs)

 

350.05

 

Performance gain (%)

 

81.23694593

 


Friday, May 29, 2009 #

I learnt something new about SOAP adapter today so thought of sharing. I never realised but BizTalk SOAP adapter by default is configured to look into Orchestration proxy code while creating a SOAP request. In other words message natively formed within orchestartion is mapped to the body (SOAP:Body) part by the adapter by using proxy code embedded in the orchestartion assembly. This became obvious when we tried to create a web request using BizTalk WCF adapter which required mapping applied on a send port to create the request (a bit clunky way in my opinion). Thanks to collegue Nick Heppleston (http://www.modhul.com/) in helping to figure this out

Wednesday, May 13, 2009 #

Business rules do not fire even when all match conditions seem to have been evaluated to true

 

Have you ever been in a situation when all match conditions in your business rule evaluated to true and still rules didn’t fire? If yes, then read on; you might have been stuck in same situation as mine.

 

Today I was working to modify a business rule that I wrote a while ago when I got completely stuck with the issue described as below. For a minute I thought that I might have unearthed a bug in Business rules engine. But then after scratching my head for sometime I realise where I was going wrong.

 

Basically, I was trying to test a simple business rule policy which on executing, followed in with all match conditions resulting in a positive outcome (Test Result: True) and still rules didn’t fire. Furthermore, I could see fact (simple .Net component) being asserted and then gracefully retracted after all match conditions have been successfully evaluated. I used DebugTrackingInterceptor to intercept all the events generated by the rule engine.

 

After much confusion, I realised that my business rule policy was configured with a long term fact which was not enabled (via registry switch). This switch and state of long term fact (and hence assertion) is not important. What is important is the fact (not B.R fact) that the event interceptor was not tracking the match conditions corresponding to the long term fact and hence resulting in this confusion. This makes sense as my long term fact being in disabled state never had a chance to assert the long term fact and hence corresponding match conditions never got fired and therefore no events tracking. What I think is missing is the fact (not B.R fact again) that just by looking at the events there is no way to tell why rules did not fire when (presumably) all match conditions resulted in a positive result. May be it is a time to write my own custom Interceptor. However for time being, I thought of sharing this just in case any of you may land up in a similar situation and may be edging towards blaming MS rules engine (like me) for this awkward looking scenario.


Friday, May 08, 2009 #

Other day I was playing with BizTalk 2009 UDDI feature. With no real background in this area, I was bound hit issues. One of the annoying ones that I came across was to do with simply trying to publish my service. After standard installation and configuration, I browsed http://localhost/uddi/ on my machine with all excitement to publish my very first service. As soon as I selected Publish option (see below) web request failed with an error “Internet explorer cannot display the web page”. 
I noticed that the web page was trying to access link over https (ssl). I couldn’t remember having selected this mode both while installing or configuring uddi. After scratching my head for sometime (including an attempt to configure my local web site with a certificate generated by myself), I stumbled upon an option to choose secure access to publish services (under the Security tab for the properties corresponding to the default site created by UDDI configuration in UDDI Service console), see figure below. I couldn’t remember selecting this; however presume that this is a default setting. Guess one of those things for beginners (like me) to watch out for.

Thursday, April 30, 2009 #

Concurrent Convoys with Time Outs
In my last project, I came across a situation when order of convoy messages could not be guaranteed. This simply implied that we should be using Concurrent convoys; problem solved, only until we stepped onto our next requirement to have timeouts implemented in case of all three (in our case) messages didn’t arrive in time. Now this turned out to be a show stopper for the reasons given below:
1.       Concurrent convoy implementation in BizTalk does not give any opportunity to use listen shape (like in sequential convoy) and hence usage of delay shape to implement timeout. The reason being very obvious.
2.       Even though the receiving part of concurrent convoy can be brought into the scope shape on which a timeout value could be set, however it won’t give an opportunity to access the messages already received (once exception routine is fired because of a timeout).
Solution:
Because of the very nature of the problem, I could not help but getting tempted towards going down a route of using sequential convoy that gives me a direct way to use listen shape and hence time out. Only problem is how to receive messages of different types in an unordered manner as non-uniform sequential convoy by its nature forces a sequence. Also, uniform sequential convoy is limited to receiving messages of a same type.
I overcame the problem by employing a uniform sequential convoy and making sure that the different types of messages (to be received by this convoy) gets converted into same type before it hits the convoy. This can be accomplished by using a custom pipeline component, which wraps the original message into a wrapper message, and by setting some key values in this wrapper message (for downstream processes to get hold of the original message). Lastly, what is left to be done in an orchestration (that implements uniform sequential convoy) is to extract the original messages and continue processing.
I list below the key components that I have used to achieve this solution.
1.       Wrapper message schema: To wrap various incoming message to the same type. As you can see below there are some key values that I have defined in the schema (like OriginalMessageType) to help me recognising the original message and related attributes. OriginalContent element in the schema holds the original xml message. To avoid xml parser to avoid parsing this, I made sure to warp the original message in a CDATA block (example below)
 
Note: Some of the attributes are purely related to the implementation of my solution and may not be required in your case.

 
2.       Custom pipeline component: To create a message of a common type from original message. This can be done by following steps below:
 
·         Grab IBase Message by hiding GetNext method of a custom-disassembler.

 

3.       Get hold of original message type: This is done to enrich wrapper message with the type of original message for downstream processes to process accordingly.

4.       Wrap original message in a new wrapper message: While doing this I have made sure that I stick in original message type in one of the distinguished fields of the wrapper message. There are few more but these are specific to my implementation only. Note the use of CDATA block.

5.       Create new message and copy original context across: I have made sure that I do not lose context supplied with the original message by copying it across. One thing to note here is that for me to be able to copy context across, I made sure that I get hold of one when pipeline Disassemble method was called earlier. Code snippets for both are below.
 
Grab Original Message Context

Copy context across

Final Piece:
Now that we have created a pipeline component that wraps the incoming messages into a common type, it is simply a matter of creating an orchestration that implements uniform sequential convoy (I will not go into details of this as this is pretty much standard). Only additional step we had to implement was to interrogate for the MessageType property on the wrapper message and pull out the original message from the wrapper message (we wrote a simple .net code which could be called from orchestration).