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