At work, the task arose: to distribute directories through Biztalk, the directories themselves are quite large - more than 300 megabytes. It was decided to use MSMQ to receive overly large messages. And now, in more detail, what was required to do this.
Of course, the first thing you can do is googling to find an example on MSDN how to implement all this (I’m going to describe it in Russian together with the changes), but I’ll just say that this example has a small one - you cannot adjust the size of the part into which the message can be divided necessary for various tasks. So let's get started.
For development we need:
- Visual Studio 2010 SP1
- Biztalk Server 2010 SDK
- Biztalk Server 2010 (for tests)
- The desire to understand everything
Open the project <Path to Biztalk Server 2010 SDK> \ AdaptersUsage \ MSMQLarge \ LargeMessages.sln. We see that the solution contains two projects: one of them in C ++. NET, the second in C #. To begin with, we need the first one in order to realize the Possibility to choose the size by which our message is split into a queue. Something needs to be corrected in the classroom. As you can see from the source code, the size is passed to the functions:
MQSendLargeMessage(unmanagedQueueData->queueHandle, &(messageData->message), MQ_SINGLE_MESSAGE, MQRTLARGE_USE_DEFAULT_PART_SIZE);
By default,
MQRTLARGE_USE_DEFAULT_PART_SIZE is definitely zero, which means using the size at the discretion of the server. For our purposes, we will add the
dwQueuePartSize private variable and change the Init private function (...) accordingly.
void Init(String* formatName, bool useAuthentication, DWORD dwQueuePartSize) { this->formatName = formatName; this->useAuthentication = useAuthentication; this->dwQueuePartSize=dwQueuePartSize; AllocUnmanagedQueueData(); }
Now it has an additional parameter responsible for setting the size during initialization. Now we need to appropriately modify the constructors that use this function.
LargeMessageQueue(String* formatName, bool useAuthentication) { Init(formatName, useAuthentication, 0); } LargeMessageQueue(String* formatName) { Init(formatName, false, 0); }
Now you can add our constructor which takes the appropriate value:
LargeMessageQueue(String* formatName, DWORD dwQueuePartSize) { Init(formatName, false, dwQueuePartSize); } LargeMessageQueue(String* formatName, bool useAuthentication, DWORD dwQueuePartSize) { Init(formatName, useAuthentication, dwQueuePartSize); }
We duplicated two standard constructors in order to be able to set an arbitrary size. A small note: you could add a parameter to the already declared constructors and correct the Init parameters, but we lose the library's backward compatibility with other solutions that you may have already implemented, or use third-party solutions based on this library.
At this stage, we get a working library with the functionality we need. It is time to test all this with a simple example. To do this, open the second project in the solution, written in C #, open the App.cs file and correct the following fragment
LargeMessageQueue queue = new LargeMessageQueue(queueFormatName); LargeMessageQueue queue = new LargeMessageQueue(queueFormatName, 3145728);
Now we are doing a complete build of the project. It is best to first build Build Clean.
At this development ends. For the test, we will create a simple BizTalk application that will take the message from the queue and put it in the : \ Demo folder.
- Create a private queue on the local computer with the name Test, when creating, you must select an option that indicates support for the transaction queue. Be sure to check the rights to receive messages from this queue by the user from which your BizTalk Server is running.
- Create a folder C: \ Demo. Again, be sure to check write permissions to the folder for the user from which your BizTalk Server is running.
- 3. Open the Biztalk administration console and create a new application, let's call it MSMQBiztalkTest. In this application, we create a Send Port of the Static One-Way Send Port type and name it MySendPort. Select the transport Type - FILE and configure it accordingly, so that it adds our messages to the C: \ Demo folder that we created earlier. Set a filter on this port with the following value BTS.ReceivePortName == MyReceivePort
- Create a new Receive Port of the One-way Receive Port type and call it MyReceivePort. For this port, create a new Receive Locations of the One-way Receive Location type with the name MSMQReceiveLocation. Select the Transport Type equal to MSMQ and configure to receive messages from our queue. For this, in the settings, set the Queue to localhost \ private $ \ test and set the Transactional to True.
- On this test BizTalk application is created, you need to start it and restart the Biztalk service.
To send a message to the queue, we use the application we created earlier in VisualStudio 2010. It works from the command line and accordingly accepts two parameters: parameters of the queue and the name of the file to be sent.
SendLargeMessage.exe DIRECT = OS: localhost \ private $ \ Test "C: \ TestData \ LargeFile.xml"
Depending on the size of the file, you will be able to watch it in the C: \ Demo directory in a few seconds and watch it grow gradually.
That's all. If someone has any questions or suggestions, I’ll be happy to answer everything in the comments.
Sources:
Large Message to MSMQ