Santry Technology Solutions, Content Management, DotNetNuke, SharePoint Consulting
Register | Login
Saturday, October 11, 2008

Sections
  
About Us
  
Partners
Downloads
  
 WWWCoder.com Resource Directory

Replicating Content to Multiple Servers
5/9/2004 8:49:44 AM

This article provides one solution for replicating content to multiple share locations. This could be useful where you have a Web application hosted on a Web farm and you wish to have files uploaded via the Web, and then replicate the uploaded files to other servers in the farm.

In this article I am presenting one solution for duplicating content across a Web farm.

If you're familiar with highly available systems that run on a Web farm; you have multiple machines serving content for your Website. The most common configuration is where you have your development machine, and once you're done with development you place the content on a middle tier server called a staging server. Once content is on the staging server, it is then replicated across the members of the production Web farm. This configuration provides a great amount of performance and redundancy for the Web site. The major drawback is if you want people to be able to upload data to the Web server, usually you have to use some kind of database solution to store the files in a centralized database rather than on the Web server itself. This is due to the fact you are never sure which Web server the file will be uploaded to, and when replication occurs again, it may delete the file since it does not exist on your staging server.

In this article we are going to present a .Net procedure that accepts the path information of a file that has been placed on a Web server, and then it copies the file to other servers via a share name. The routine will check to see which server in the share name array it is and replicate the content to other machines in the array.

In this example we will need to specify a delimited string which will be our paths to the shares which are members of the farm. In addition to this we will specify a privileged account that will be used to access the share. Modify the appSettings section of the  Web.config file to contain the following:

<add key="ADsUserName"
value="domain\accountname" />
<!--To be replaced with your network setting-->
<add key="ADsPassword" value="password" />
<!--To be replaced with your network setting-->
<add key="FarmMembers" value="\\server1\share$;\\server2\share$" />
<!--Enter a semicolon delimited string of share paths to directory of the application root of your web, for example if your root is located on c:\InetPub\wwwroot\ you could use \\server\c$\Inetpub\wwwroot\ as your share as long as the account has admin privs to use dollar shares --->


The next thing we need to do is create a WebFarm.vb class which we will use to call from our aspx pages. Create the class and then import the System.IO class for manipulating files, System.Security.Principal for account impersonation, and System.Configuration for working with our web.config file.

Imports System.IO
Imports System.Security.Principal Imports System.Configuration

Next make a declaration to the advapi32..dll API, this will allow us to execute the code under a privileged account that has permissions to all the server shares that were specified.

Public Class Logon
Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As String, _
ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, ByRef phToken As Integer) As Boolean
End Class

Next declare some constants to be passed to the Logon class, whether to logon as an interactive user, or using clear text. In our example here we will be logging on as an interactive user to access the share on the network

Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_NETWORK_CLEARTEXT As Integer = 3
'This parameter causes LogonUser to create a primary token.
Const LOGON32_LOGON_INTERACTIVE As Integer = 2

Private DomainName As String
Private UserAccount As String
Private Password As String
Private CurrentMachine As String = System.Environment.MachineName
Private aryShares As String()

Here we call a routine that is going to populate the variables we declared above. The variables will be populated with the username and password we're going to use to access the share, and create an array of the shares that we want files replicated to.
'GetFarmValues
'Description: Used to parse out information defined in the
' Web.config file for account information and shares.
Private Sub GetFarmValues()
'points to the root directory of the application.
Dim strServers As String = ConfigurationSettings.AppSettings("FarmMembers")
aryShares = Split(strServers, ";")
Password = .Configuration.ConfigurationSettings.AppSettings("ADsPassword")
UserAccount = Mid(ConfigurationSettings.AppSettings("ADsUserName"), _
InStr(ConfigurationSettings.AppSettings("ADsUserName"), "\") + 1)
DomainName = Left(ConfigurationSettings.AppSettings("ADsUserName"), _
InStr(ConfigurationSettings.AppSettings("ADsUserName"), "\") - 1)
End Sub

The following procedure accepts InPath as the local path that the file is being copied to. InFile is the name of the file that we want to copy. And InAppRoot is the application root directory of the path. We use this to determine the path for the share to its web directories.

Public Sub CopyFileToShare(ByVal InPath As String, ByVal InFile As String, _
ByVal InAppRoot As String)
Dim sDestination As String
Dim hToken As Integer
Dim iPtrToken As IntPtr
GetFarmValues()
Dim LocalPath As String = InPath & InFile
Dim i As Integer
Dim loggedOn As Boolean = Logon.LogonUser(UserAccount, DomainName, Password, _
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken)
If loggedOn Then
iPtrToken = New IntPtr(hToken)
Dim ImpersonatedIdentity As New WindowsIdentity(iPtrToken)
Dim MyImpersonation As WindowsImpersonationContext = ImpersonatedIdentity.Impersonate()
'do routine.
Try
For i = 0 To UBound(aryShares)
'check out the share in the array against the current machine.
If InStr(LCase(aryShares(i)), LCase(CurrentMachine)) = 0 Then
'this is a different machine than the local machine.
'we need to figure out the root of the servers.
sDestination = Replace(InPath, InAppRoot, aryShares(i)) & InFile
'if it's there delete it first.
File.Delete(sDestination)
File.Copy(LocalPath, sDestination)
End If
Next
Catch ex As Exception
'file copy failed.
End Try
MyImpersonation.Undo()
End IfEnd Sub

Then from our aspx file for example, if we had an upload routine that accepted a file from a user via the Web, once the file was uploaded to the server, we would immediately call our newly created class and copy that file to other servers in our share array:

Dim objWebFarm As New WebFarm
objWebFarm.CopyFileToShare(Request.MapPath("c:\inetpub\wwwroot\myapp\", _
strFileName, Server.MapPath(Request.ApplicationPath))
objWebFarm = Nothing

By:
Patrick Santry,
MCT, MCSE, MCSA, MCP+SB, contributor of "Windows 2003 Server - The Complete Reference", Co-Author of
"Administering IIS 5.0" both books published by McGraw-Hill. In
addition, Patrick has written several articles and co-authored several books on
Microsoft certification. You can view his personal website at
http://www.santry.com/.


Related Articles
   Related Document Use DFS for Storing Your ASP.Net Application


Page Options:
format for printing  Format for Printer
email article  Email Page
add to your favorites   Add to Favorites
How would you rate the quality of this content?
Poor - - Excellent
Comments?
Overall Rating:
Comments Left:
Left on 6/18/2004 2:05:21 AM by Anonymous
Comments: I have been looking for something like this for over 6 weeks. A major $20,000 upgrade had to be postponed because I overlooked a simple difference in the nature of a Web farm architecture... THANKS!
Left on 4/19/2004 4:26:34 PM by Anonymous
Comments: Unclear how to set-up a user account to do this.
Left on 4/14/2004 2:24:19 PM by Anonymous
Comments: Just as a reference for folks trying to set security and impersonation in IIS for this code, you can reference the following KB article: http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q306158

- P. Santry
No ratings available.
Left on 1/14/2004 9:41:55 AM by Anonymous
Comments: One thing on the NAS, if you store everything on the NAS, you will need to make sure you have some redundancy somehow. If you don't, and your NAS goes down, then you still have a single point of failure and negating the benefits that you get from the Web farm.
No ratings available.
Left on 9/15/2003 10:48:49 AM by Anonymous
Comments: A nice solution if you are load-balancing a single site.  For multiple sites I've had good luck so far with using DFS, but the best solution still seems to be a NAS.  I'm getting one soon hopefully.
Left on 8/27/2003 11:10:34 AM by Anonymous
Comments: Perfect. Just what we were looking for. Thanks and great job.
Left on 8/9/2003 6:42:41 PM by Anonymous
Comments: Great idea!  We've been playing with other options, but this is really slick!  thanks for the great article!
  

 Latest Articles
  

 Latest News
  

 

Spotlight
Syndication

 


 


Digg This
 


DotNetNuke Platinum Benefactor

  
 

 Terms Of Use | Privacy Statement
 Copyright 2008 - Santry Technology Solutions, Box 172, Girard, PA 16417, (814) 774-0970