One of the most common BizTalk architectures I have seen across customers is as follows:
With this configuration, BizTalk server is deployed using a high availability configuration that will work for most of cases in which the environment is receiving information using, for instance, the WCF http binding adapter only. The NLB (hardware or software) is spreading the requests among all the BizTalk servers in the group.
For the database layer, most of customers provide high availability setting up an MCS cluster (virtual or physical) and typically they also provide HA for the SQL Server Agent service (or at least they must) , action that opens an interesting option to solve the most common problem when using the FTP BizTalk receiving adapter:
Having more than one receiving BizTalk host instance for the FTP adapter can cause duplicated messages.
The FTP protocol does not blocks the file, therefore, having more that one host instance configured to process receive locations could cause a duplicated message. For instance, if we have a look at our architecture it can happen that host instance on server 1 will go to pick up files to the FTP server. Because host instances are fully agnostic of what the other host instances in the group are doing, the one running in server 2 might go also to the FTP server at the same time than Server 1. If the file is bigger enough BizTalk will pick up the same message twice. To avoid this issue we normally have two options:
- Create an MCS cluster at the BizTalk layer and cluster the receiving FTP host instance (preferred option)
- Disable all the host instances from starting and enabling it in one server only. With this action, just one host instance will be executing and now BizTalk will not get duplicated messages (not recommended as we are having manual HA for FTP host instances)
So what do we do if we cannot implement BizTalk clustering ?
As Microsoft always recommends clustering the SQL Server Agent you could leverage on SQL Server jobs to execute a Powershell script that will check BizTalk Services status remotely.
Have a look at the following architecture:
The PowerShell script that will run under the SQL Server Agent and it will ensure that your FTP BizTalk hostinstance is running only in 1 server. If that scripts runs and finds out that there are more hostinstances running, it will shutdown those processes and will enable the hostinstnace only in 1 server.
Description of the script
This Powershell script gives a mechanism to provide High availability for windows services, when there is no cluster set up (or when it cannot be used). As a BizTalk engineer, I visited many customers that need to provide HA
to BizTalk FTP hostinstances and they did not set up an MS cluster across the BizTalk group.
The SQL Server account that you use to execute this job must be part of the BizTalk Administrator group because and it needs to have permissions to start and stop services in all of your BizTalk Servers.
This will be the name of the windows Service that you want to provide HA.Don’t forget to add the escape character for the BizTalk Services name, as they have the $ symbol, like in this “BTSSvc`$BizTalkServerApplication” .
This is the place in which you have to provide the Server Names that will be part of the HA configuration.
This is the Server Status List. By status here we refer to the status of the service in all of the Servers that are part of the $ServerList array. The number of items here should be the same than in the $ServerList array.
Change this parameter if you want a different default server. This will be the position in the $ServerList array (So zero, for the first server). The script will know which server should be used as the Default one in the HA configuration. So it will always try to start the service in this Server First.
Yes! the script is logging information. The Script will be logging all the information to the file specified here.
Example of parameters:
$ServiceName = “BTSSvc`$BizTalkServerApplication”
$ServerStatusList=@(0,0,0,0) #This is the Server Status List. By status here we refer to the status of the service in all of the Servers that are part of the $ServerList array. The number of items here should be the same than in the $ServerList array.
$DefaultServer = 1 #Change this parameter if you want a different default server. This will be the position in the $ServerList array (So zero, for the first server). The script will know which server should be used as the Default one in the HA configuration. So it will always try to start the service in this Server First.
$MoreThanOneServiceActive= 0 #If there are more than one service active, we change this to 1, as the objective of this script is to ensure only one instance of the service is running across all the Servers in
$LogFilePath=”C:\Logs\PowerShellLog.log” #the Script will be logging all the information to the file specified here.
After you adapt the script parameters within the code, you can now create the SQL Server agent job that will call the script. After the changes, your architecture would look something similar to the following diagram:
Downloading the code:
You can download the code from MSDN code gallery here: