I had to implement a fallback system in case one of my primary servers is not available anymore because of any reason. There were no option to access servers over a loadbalancer or something else then a direct routing to each server.
After some compassion's how much time I gone waste for each request between usage of sockets or HttpWebRequest / WebRequest I decided to work directly with Sockets.
The implementation I decided to go for were quite easy (remember: keep it simple as possible) and its fast like hell - 9ms I'm loosing each check if the server is available or not. We use 2 servers - so I have to remember that there is a total of 18ms I'm loosing each time we have a running cycle to analyse data. In general my tests gave showed me that 5 of the 9 ms are used for DNS.GetHostEntry(ServerName) - if you can use IP-Addresses then I suggest to do it that way. Check out one of my previous post about this DNS.GetHostEntry(ServerName) - IPAddress.Parse("127.0.0.1") vs. Dns.GetHostEntry("127.0.0.1")
With those ~20ms we can leave very good because a cycle needs right now something around 2.5min and it can be a max. of 15min. So how to solve this is the question, here the codesample from MSDN which I adapted and using to validate if my servers are online: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx
Formatted Code is available here: http://www.ronischuetz.com/code/CheckIfServerIsAvailable.htm
1: private static bool ConnectSocket(string server, int port)
2: {3: Stopwatch sp = new Stopwatch();
4: IPHostEntry hostEntry = null;
5: bool result = false;
6: sp.Start();7: // Get host related information.
8: hostEntry = Dns.GetHostEntry(server); 9: sp.Stop();10: Log.Info(string.Format("ConnectSocket->Dns.GetHostEntry({0}) needed: {1}ms ",server, sp.ElapsedMilliseconds));
11: sp.Reset(); 12: 13: // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
14: // an exception that occurs when the host IP Address is not compatible with the address family
15: // (typical in the IPv6 case).
16: foreach (IPAddress address in hostEntry.AddressList)
17: { 18: sp.Start();19: IPEndPoint ipe = new IPEndPoint(address, port);
20: Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
21: tempSocket.ReceiveTimeout = 1000; 22: tempSocket.SendTimeout = 1000;23: // this is very important!!! Do not delete this.
24: tempSocket.NoDelay = true;
25: 26: try
27: { 28: tempSocket.Connect(ipe);29: #region Status Check
30: if (tempSocket.Connected)
31: {32: #region Connnected Section
33: result = true;
34: if (tempSocket != null)
35: {36: try
37: { 38: tempSocket.Shutdown(SocketShutdown.Both); 39: tempSocket.Close(); 40: }41: catch (Exception ex)
42: {43: // do nothing - only release resources and don't let the system fuck up
44: }45: finally
46: {47: tempSocket = null;
48: } 49: }50: #endregion Connnected Section
51: break;
52: }53: else
54: {55: continue;
56: }57: #endregion End Status Check
58: }59: catch (Exception ex)
60: {61: string title = string.Format("Could not connect to server:{0}:{1} - " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, server, port);
62: Log.Info(title); 63: Log.Fatal(title);64: result = false;
65: } 66: 67: sp.Stop();68: Log.Info(string.Format("ConnectSocket->hostEntry.AddressList({0}) needed: {1}ms to connect to server ", ipe.Address.ToString(), sp.ElapsedMilliseconds));
69: sp.Reset(); 70: }71: return result;
72: }

No comments:
Post a Comment