A quiet release by Microsoft this month was the new version of its free BizTalk performance and stress test tool – Microsoft BizTalk LoadGen 2007.
Come to think about it BizTalk LoadGen 2004 unfortunately also never got much praise, even though it is used quite a lot by Microsoft to test BizTalk. You can use it to generate messages and perform stress and performance tests on your BizTalk Server and other servers.
The tool in a nutshell is a command line utility called LoadGenConsole.exe that takes an XML configuration file and generates the load tests described in the configuration file. The 2007 version of LoadGen can be used to simulate load in several types of transport (file, HTTP, MQSeries, MSMQ, SOAP, WSE, WSS, WCF) and to monitor certain types of systems (file, MQSeries, MSMQ, MSMQ Large files, performance counters, SQL Server).
I created a simple BizTalk solution that consists of two schemas, PO and POAck, a map, and an orchestration that exposes a port with a public Receive-Send port type.
The map copies the purchase order number and datetime to POAck, and determines if the purchase order is accepted or not based on the total price of the PO: if the total is less than or equal to 1000 it’s accepted otherwise rejected. The map looks like this:
The scripting functoid is an Inline C# containing this in the script:
public string POAckStatus(bool lowPrice)
{
if (lowPrice == true)
return “Accepted”;
else
return “Rejected”;
}
The orchestration is also very simple, receiving a PO, calling the map and returning the POAck. The only little trick is to make sure the port type is Public otherwise we won’t be able to expose the orchestration as a WCF service. Here is how it looks like in the designer:
After deploying the solution, I fired up the BizTalk WCF Service Publishing Wizard and:
- Selected WCF-BasicHttp as the transport type
- Selected for it to create BizTalk receive locations on the application where the BizTalk solution was deployed
- Selected “Publish BizTalk orchestrations as WCF service”
- Browsed to my solution’s DLL, selected the Port_ProcessPO as the port to export
- Chose http://BTLoadGen2007WcfTest/ as the target namespace
- Chose http://localhost/BTLoadGen2007WcfTest as the location
And voila! The wizard creates the service in IIS and creates the receive port in the BizTalk orchestration. After this I had to bind the orchestration to the new port, start the orchestration and port, configure permissions on the new IIS virtual directory created by the wizard, and enable the WCF performance counters on the service.
To enable the WCF performance counters on the service you edit the Web.config file created by the wizard and add the following line inside the <System.ServiceModel> node:
<diagnostics performanceCountersEnabled=“All“ />
[EDIT] The above is for WCF 3.0. If you are using WCF 3.5 then add the following line to web.config:
<diagnostics performanceCounters=“All“ />
Then restart the BizTalk host so that the counters show up on the performance counters. Now that I have the orchestration exposed as a WCF service I can look into how to use LoadGen 2007 to test it. LoadGen lets you either submit the same file over and over again for each test or you can create a template file with fields that it modifies for each file. There are a lot of configuration options so make sure you review the help that comes with the product. The template file I created, called LoadGen2007WcfTestSample.xml, was:
<ns0:PO DateTime=“DateTime_0“ xmlns:ns0=“http://BTLoadGen2007WcfTest/PO“>
<PONum>PONum_0</PONum>
<Item>
<Id>Id_0</Id>
<Description>Static Description</Description>
<Quantity>Quantity_0</Quantity>
<Price>Price_0</Price>
<UOM>Static UOM</UOM>
</Item>
</ns0:PO>
To then get LoadGen to populate the fields with values ending with “_0′ on the file above with proper values during the test I created a file that controls the message creation. I called it LoadGen2007WcfTestMessageCreator.xml, and its contents are:
<MessageCreator SourceFilePath=“C:\Program Files\LoadGen\Bins\LoadGen2007WcfTestSample.xml“ OutEncoding=“utf-8“>
<Field>
<InitialValue>PONum_0</InitialValue>
<DataType>Integer</DataType>
<InputFilePath></InputFilePath>
<ContentMinSize>1</ContentMinSize>
<ContentMaxSize>2000</ContentMaxSize>
<AllowDuplicates>True</AllowDuplicates>
</Field>
<Field>
<InitialValue>Id_0</InitialValue>
<DataType>Guid</DataType>
<InputFilePath></InputFilePath>
<ContentMinSize>1</ContentMinSize>
<ContentMaxSize>1024</ContentMaxSize>
<AllowDuplicates>True</AllowDuplicates>
</Field>
<Field>
<InitialValue>Quantity_0</InitialValue>
<DataType>Integer</DataType>
<InputFilePath></InputFilePath>
<ContentMinSize>1</ContentMinSize>
<ContentMaxSize>50</ContentMaxSize>
<AllowDuplicates>True</AllowDuplicates>
</Field>
<Field>
<InitialValue>Price_0</InitialValue>
<DataType>Integer</DataType>
<InputFilePath></InputFilePath>
<ContentMinSize>1</ContentMinSize>
<ContentMaxSize>2000</ContentMaxSize>
<AllowDuplicates>False</AllowDuplicates>
</Field>
<Field>
<InitialValue>DateTime_0</InitialValue>
<DataType>Timestamp</DataType>
<InputFilePath></InputFilePath>
<ContentMinSize></ContentMinSize>
<ContentMaxSize></ContentMaxSize>
<AllowDuplicates>True</AllowDuplicates>
</Field>
</MessageCreator>
This configuration file tells LoadGen to search for the string in the InitialValue element and replace it for the random value based on the rest of the parameters under Field (that’s right, you put the string for it to search and replace, not the name of the XML node on your template file). Two more steps to go: configure LoadGen with an endpoint to our WCF service and create the actual load test configuration file. To configure LoadGen to work with WCF you must edit the LoadGenConsole.config file and add a <System.ServiceModel> element under <Configuration>. For my test I added the following:
<system.serviceModel>
<client>
<endpoint name=“LoadGen2007WcfTestPOProcessEndpoint“
address=“http://localhost//BTLoadGen2007WcfTest/LoadGen2007WcfTest_POProcess_Port_ProcessPO.svc“
binding=“basicHttpBinding“
bindingConfiguration=“LoadGen2007WcfTestPOProcessBinding“
contract=“WcfTransport.IChannelAsyncNonTransactional“/>
</client>
<bindings>
<basicHttpBinding>
<binding name=“LoadGen2007WcfTestPOProcessBinding“
openTimeout=“23:59:59“ receiveTimeout=“23:59:59“ closeTimeout=“23:59:59“ sendTimeout=“23:59:59“>
<security mode=“None“>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
Finally, we must create the configuration file that gets passed to the command line tool containing sections detailing the work LoadGen should do. I called the file LoadGen2007WcfTestConfig.xml and it contains:
<LoadGenFramework>
<CommonSection>
<LoadGenVersion>2</LoadGenVersion>
<SleepInterval>2000</SleepInterval>
<OptimizeLimitFileSize>204800</OptimizeLimitFileSize>
<NumThreadsPerSection>5</NumThreadsPerSection>
<RetryInterval>1000</RetryInterval>
<StopMode Mode=“Time“>
<TotalTime>300</TotalTime>
</StopMode>
</CommonSection>
<Section Name=“LoadGen2007WcfTest“>
<Transport Name=“LoadGen2007WcfTest“>
<Assembly>WcfTransport.dll/WcfTransport.WcfTransport</Assembly>
</Transport>
<SrcFilePath>C:\Program Files\LoadGen\Bins\LoadGen2007WcfTestSample.xml</SrcFilePath>
<LotSizePerInterval>20</LotSizePerInterval>
<DstLocation>
<Parameters>
<ClientType>WcfTwoWays</ClientType>
<Transactional>False</Transactional>
<ClientEndPointName>LoadGen2007WcfTestPOProcessEndpoint</ClientEndPointName>
<IsSynchronous>False</IsSynchronous>
<MessageAutoGenerate>False</MessageAutoGenerate>
<LogReqMessage>True</LogReqMessage>
<LogRespMessage>True</LogRespMessage>
</Parameters>
</DstLocation>
<MessageCreator Mode=“Asynchronous“>
<SleepInterval>2000</SleepInterval>
<QueueLength>1000</QueueLength>
<Assembly>CustomMC.dll/CustomMC.CustomMC</Assembly>
<TemplateFilePath>C:\Program Files\LoadGen\Bins\LoadGen2007WcfTestMessageCreator.xml</TemplateFilePath>
</MessageCreator>
</Section>
</LoadGenFramework>
This file tells LoadGen to create five threads that will try to generate up to 20 messages (LotSizePerInterval) every 2 seconds (SleepInterval) over a period of five minutes (StopMode=Time, TotalTime = 300). LoadGen also installs a few performance counters for each of its supported transports and monitors. For the WCF adapter it adds “Messages sent/sec” and “Total Messages sent to the target”. For this test I chose to monitor:
- LoadGen:WcfTransport
- “Messages sent/sec” – LoadGen’s count of messages it sent
- XLANG/s Orchestrations
- “Orchestrations created/sec”
- “Orchestrations completed/sec”
- BizTalk:Message Box:Host Counters
- “Host Queue – Length” – BizTalk queue
- BizTalk:Message Agent
- “Message delivery throttling state” – Outbound throttling
- “Message publishing throttling state” – Inbound throttling
- ServiceModelService 3.0.0.0
- “Calls Outstanding” – Calls to the Service being processed
- “Calls per Second” for my WCF service
These give me an overview of how BizTalk is keeping up with LoadGen. Note that the LoadGen test has to be running before the instance of the performance counter can be selected, so fire up the LoadGen test first then add the performance counter to the counter log.
Finally, on to the test! I started the performance counter log and ran the LoadGen test by firing up the command prompt and ran it passing the configuration XML as a parameter:
As you can see after five minutes it sent an average of 25.1 messages per second to the Orchestration exposed as a WCF Service on my virtual machine, totaling at 7606 messages. Not bad! The throttling counters show message publishing and delivery throttling were enabled about 5 times for a second or two during the test, and the host queue never went over 14. Since there was some throttling BizTalk keeps processing the last messages for about 30 seconds after LoadGen finishes the test.
The only issue I found is with the request messages logged (enabled by adding <LogReqMessage>True</LogReqMessage> to the DSTLocation part of the configuration file). It logs the template file with the _0 values for each message sent instead of the actual message generated by the message creator. I turned on message tracking in BizTalk and I can see the messages sent to BizTalk are populated correctly, as below, so the request message tracking with WCF and message creator seems to have a bug:
<ns0:PO DateTime=“Mon, 05 Nov 2007 10:22:35:406014“ xmlns:ns0=“http://BTLoadGen2007WcfTest/PO“>
<PONum>108</PONum>
<Item>
<Id>3ba6047d-1ed9-4efe-a338-5088dfb2774c</Id>
<Description>Static Description</Description>
<Quantity>37</Quantity>
<Price>939</Price>
<UOM>Static UOM</UOM>
</Item>
</ns0:PO>
And here is the POAck message generated by in response:
<s:Envelope xmlns:s=“http://schemas.xmlsoap.org/soap/envelope/“>
<s:Body>
<ns0:POAck xmlns:ns0=“http://BTLoadGen2007WcfTest/POAck“>
<PONum>108</PONum>
<PODateTime>Mon, 05 Nov 2007 11:06:31:739888</PODateTime>
<Status>Rejected</Status>
<POTotalPrice>1062</POTotalPrice>
</ns0:POAck>
</s:Body>
</s:Envelope>
In conclusion, LoadGen is no comparison to Visual Studio Load Tests, as expected, but is still a very powerful (and free) tool for testing your BizTalk solutions. It is great to determine the throughput and capacity of your solution. Also, if combined with BizUnit, you can implement a serious BizTalk automated testing environment.
As a leaving note, don’t overlook the fact that you can also use this tool to test other solutions that use WCF, HTTP, SOAP, file pickups, etc. It isn’t restricted only to BizTalk testing.
Hey I really enjoyed these articles. Well written and very applicable to what I need.
Keep them coming.
Thiago – nice article!!
I’d be interested to see what perf difference there was if you hosted your WCF Service in BTS (through a WCF Custom adapter) and leave IIS out of the picture.
Also to note – when you run the WCF Publishing Wizard, then make sure there is not an old version of the DLL in the GAC, otherwise (part of .NET 2.0) the Wizard will always pick up the old one in the GAC :-(.
Great article!!!
Hi, very nice article, is it possible to dropmethe artfacts in order to play with your demo.
Thanks
When I add the line in the service web config, I get error message indicating that this is not a recognized attribute.
Thanks for your help
the line is the “diagnostics performanceCountersEnabled=“All“”
Please ignore allmy precedent comments, It is working fine and hope if the doc that ships with new version are so nicely done as your artcile. Thanks for making this available for the community
Salam, thank you for your comments, I’m glad you got it working and that my article helped.
Please visit my blog at http://82.225.56.11/BlogEngine which I have just made public. I added a link to your article in my first blog and hope you don’t mind
Heya,
I am new to LoadGen tool and getting the following error in the eventlog
when a webservice is called from LoadGen. Please could someone give me a hand?
——————————————————————————————–
Start() Section [EMIS-To-CaseNotes] encountered the following exception!LoadGen.ConfigException: Missing!
at SOAPTransport.SOAPTransport.set_DstLocation(String[] value)
at LoadGen.NormalSectionThread.Start()
—————————————————————————————
config file
~~~~~~~~~~~
1
458930
1
1000
1
1000
5
1000
SOAPTransport.dll/SOAPTransport.SOAPTransport
7
C:Program FilesCompanyNameMyToolTest.XML
http://localhost/MyService/service.asmx
SOAPAction: “http://www.sungard.com/vivista/integrationservices/csw/QMessage”
<?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”><soap:Body><QMessage xmlns=”http://tempuri.org/”>
</QMessage></soap:Body></soap:Envelope>
False
C:HTTP-Response
UTF-8
You might also be interested in WCFStorm
(here : http://geekswithblogs.net/Erik/archive/2009/04/02/130664.aspx)
It can create both LOAD/Perfomance and Functional test cases! And it works on both WCF and Web services.