Wake Up SharePoint Sites on multiple Front Ends
Par Mathieu le mercredi 2 septembre 2009, 19:57 - Lien permanent
So, you have multiple Front Ends behind a Load Balancer and you want to wake up
each front end to enable the content to be served as fast as possible.
Here is a small architecture with 3 Front Ends (click to zoom):
Front End A: 10.0.0.1
Front End B: 10.0.0.2
Front End C: 10.0.0.3
Each Front Ends will respond to http://intranet.fabrikam.com because their
IIS Host Headers are configured to “intranet.fabrikam.com”, but if you use this
URL its the “Load Balancer” which is going to reply.
So, How can you access http://intranet.fabrikam.com on Front End A
?
You have to send the HTTP Request to the Front End A’s IP Address
(10.0.0.1) using “intranet.fabrikam.com” as the host value in the
HTTP Request.
Here is the HTTP Request you must build to access http://intranet.fabrika.com :
GET / HTTP/1.1
Accept: application/x-ms-application, */*
Accept-Language: en,fr-BE;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729
Accept-Encoding: gzip, deflate
Host: intranet.fabrikam.com
Connection: Keep-Alive
Then you have to send it to Front End A’s IP Address (10.0.0.1) How
to send that request to that IP Address ? There are many ways to do that:
- Using System.Net.Sockets.Socket
- Using WebClient or WebRequest (method A)
- Using WebClient or WebRequest (method B)
There is a major drawback with this method, you’ll have to handle
authentication manually (easy with Basic Authentication, pretty hard with Ntlm
or Kerberos)
Second Method (Using WebClient or WebRequest (method A)):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
string strHttpRequest = String.Concat("GET / HTTP/1.1rn", "Accept: application/x-ms-application, */*rn", "Accept-Language: en,fr-BE;q=0.5rn", "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729rn", "Accept-Encoding: gzip, deflatern", "Host: intranet.fabrikam.comrn", "Connection: Keep-Alivernrn"); //Create a IPv4 TCP Socket Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Connect to the Front End A's IP address on HTTP Port (80) socketClient.Connect(IPAddress.Parse("10.0.0.1"), 80); //Send the Http Request socketClient.Send(Encoding.Default.GetBytes(strHttpRequest)); StringBuilder sbHttpResponse = new StringBuilder(); byte[] bReceiveBuffer = new byte[4096]; int iReceivedBytes = 0; //Process the Http Response while ((iReceivedBytes = socketClient.Receive(bReceiveBuffer)) > 0) sbHttpResponse.Append(Encoding.Default.GetString(bReceiveBuffer, 0, iReceivedBytes)); //Output the Http Response Console.WriteLine(sbHttpResponse.ToString()); |
Apparently this method will only work with .NET FrameWork 4.0, actually it
doesn't (.NET 3.5) because you cannot alter the “Host” header value(https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=384456)
Additionally, there is a way (hack) to access the internal collection of
headers to bypass the validation:
http://blog.scoftware.com/post/2009/07/28/SOLUTION-HttpWebRequest-raw-headers.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Create a HttpWebRequest to Front End A's IP Address HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create("http://10.0.0.1"); //Modify Host header to reach intranet.fabrikam.com myHttpWebRequest.Headers[HttpRequestHeader.Host] = "intranet.fabrikam.com"; //Process Response HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); Stream streamResponse = myHttpWebResponse.GetResponseStream(); StreamReader streamReader = new StreamReader(streamResponse); string strHttpResponse = streamReader.ReadToEnd(); //Output Response Console.WriteLine(strHttpResponse); streamResponse.Close(); streamReader.Close(); myHttpWebResponse.Close(); |
Third Method (Using WebClient or WebRequest (method
B)):
Using the Proxy property of WebClient you can target http://intranet.fabrikam.com and connect to
10.0.0.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Create a WebClient WebClient webClient = new WebClient(); //You can eventulay set a Username / Password as NetworkCredentials webClient.Credentials = new NetworkCredential("username", "password"); //The Front End A's IP Address to connect to webClient.Proxy = new WebProxy("10.0.0.1"); //Will set the correct Host Header Stream streamResponse = webClient.OpenRead("http://intranet.fabrikam.com"); //Process the HttpResponse StreamReader streamReader = new StreamReader(streamResponse); string strHttpResponse = streamReader.ReadToEnd(); //Output the HttpResponse Console.WriteLine(strHttpResponse); streamResponse.Close(); webClient.Dispose(); |
That’s all for today !