BizTalk: Optimizing For High Throughput

In a customer project we made the observation that receiving many large IDOCs from a SAP system was really slow. We were using a WCF-Custom receive location and the port had a map. The BizTalk group consists of multiple application servers but it was clear that only one BizTalk server was receiving the IDOCs at a time. Neither the network nor the cpu were significantly used. There had to be something we could do to improve performance.

The real problem is the transactional model which BizTalk is using. The adapter needs to physically receive one IDOC. It constructs a well-understood XML message from it using the XML disassembler and performs a map. The result is published to the messagebox and the IDOC is signaled as received. Basically assuming Microsoft did a good job concerning their performance, most of the time should be lost inside the map:

image

If you take a look at the physical connection between the SAP system and the BizTalk server you see a short transfer of one IDOC followed by a lengthy wait. To improve throughput we had the need to reduce these wait times. The extra challenge was to avoid introducing high costs or risks.

The solution was to remove the map and to replace the XML disassembler with the pass-through pipeline:

image

This obviously changed the resulting messages. The receive port was directly bound to a MSMQ send port using a local queue. The queue exists on all BizTalk application server to increase load balancing. A second receive location was added to receive messages from that queue and to do the needed work (XML disassembler + map).

The solution even allows to switch between both behaviors on the fly through enabling/disabling the correct receive locations. We only used proven technology and already existing BizTalk artifacts.

The throughput increased by roughly 300% but your mileage may vary. You should also consider that using queues makes your application server stateful.

Posted in architecture, BizTalk, coding | Leave a comment

BizTalk error: Data at the root level is invalid.

Problem: My orchestration looks perfectly fine with no error symbols anywhere but whenever I try to build the solution I get:

Error 1 Data at the root level is invalid. Line 1, position 1. C:\…\MyProject\MyOrchestration.odx 1 1

Cause: I was moving the orchestration file from one BizTalk project to another through holding shift and doing drag’n’drop in the solution explorer.

The btproj file has this new content:

<ItemGroup>
    <Schema Include=”MyOrchestration.odx”>
        <TypeName>MyOrchestration</TypeName>
        <Namespace>MyNamespace</Namespace>
    </Schema>
</ItemGroup>

Solution: The move operation within Visual Studio is broken. You either have to do it in a different way (maybe add existing item?) or you adjust the project file after moving the orchestration:

<ItemGroup>
    <XLang Include=”MyOrchestration.odx”>
        <TypeName>MyOrchestration</TypeName>
        <Namespace>MyNamespace</Namespace>
    </XLang>
</ItemGroup>

The error should be gone.

Posted in BizTalk, coding | Leave a comment

Linq Kwik-e: Order by

Imagine you are writing a SQL select statement to read all products from your database ordered by category and then by name, it would look like:

SELECT *
FROM products
ORDER BY category, name

Please note that my textual description follows the notation of the order statements.

Now lets imagine we have a list of products in C# and want to sort them the same way using Linq:

image

As you can see, it follows the natural description.

I like to directly use the Linq extension methods instead of Linq so I was used to write the same as:

image

To get the same ordered list as in the samples before, I had to reverse the order of the orderby statements. This feels very unnatural and is easy to get wrong. Luckily I discovered the ThenBy() method:

image

This way, I can write the statements in the same order as I was used to!

You may want to read my earlier Linq Kwik-e as well Zwinkerndes Smiley

Posted in C#, coding, Linq | Leave a comment