2016-06-07 66 views
0

我有一個特殊的套接字監聽器,它在它的線程中工作。從外部程序獲取更新數據庫的命令是工作。當命令來到套接字我打電話特殊的方法,從數據庫更新我的應用程序緩存。來自套接字監聽器的處理命令的延遲

我有一個問題,即從外部程序發送命令和在我的應用程序(ASP .NET應用程序)中處理該命令之間的延遲。每天我的應用程序都會在凌晨4點重新開始,到今天結束時,我會延遲大約1-2個小時。

我該如何減少這種延遲?

您可以在下方找到我的聽衆代碼。

謝謝。

public delegate void OnECIGetCommand(string command); 

public class ECIMain 
{ 

    protected Socket socket; 
    protected string ip; 
    protected int port; 

    private static ECIMain INSTANCE = null; 

    const int receivedDataSize = 250; 
    protected static byte[] buffer = new byte[ receivedDataSize ]; 
    protected static StringBuilder sb;        

    protected static DoWorkEventHandler onCommand;    

    private ECIMain() 
    { 
     socket = new Socket(AddressFamily.InterNetwork, 
        SocketType.Stream, ProtocolType.Tcp); 
     sb = new StringBuilder(); 
    } 

    private void StartSocket() 
    { 
     sb.Clear(); 
     socket.Listen(1); 
     socket.BeginAccept(null, receivedDataSize, 
       new AsyncCallback(AcceptReceiveDataCallback), socket); 
    } 

    private static void AcceptReceiveDataCallback(IAsyncResult ar) 
    { 
     // Get the socket that handles the client request. 
     Socket listener = (Socket)ar.AsyncState; 

     // End the operation and display the received data on the console. 
     byte[] Buffer; 
     int bytesTransferred; 
     Socket handler = listener.EndAccept(out Buffer, 
         out bytesTransferred, ar); 
     HandleBuff(bytesTransferred, Buffer); 

     // Create the state object for the asynchronous receive. 
     handler.BeginReceive(buffer, 0, receivedDataSize, 
       SocketFlags.None, new AsyncCallback(ReadCallback), handler); 
    } 

    private static void HandleBuff(int size, byte[] buff) 
    { 
     if (size > 0) 
     { 
      // There might be more data, so store the data received so far. 
      sb.Append(Encoding.ASCII.GetString(buff, 0, size)); 

      // Check for end-of-file tag. If it is not there, read more data. 
      var content = sb.ToString(); 
      int pos = -1; 
      if ((pos = content.IndexOf("</cmd>")) > -1) 
      { 
       // All the data has been read from the 
       // client. 
       pos += 6; 
       if(pos < content.Length) 
        content = content.Remove(pos); 


       var startPos = content.LastIndexOf("<cmd>"); 
       if(startPos > -1) 
       { 
        if (startPos > 0)  
          content = content.Remove(0, startPos); 
        BackgroundWorker worker = new BackgroundWorker(); 
        worker.DoWork += onCommand; 
        worker.RunWorkerAsync(content); 

       } 
       sb.Remove(0, pos); 
      } 
     } 
    } 

    private static void ReadCallback(IAsyncResult ar) 
    { 
     // Retrieve the state object and the handler socket 
     // from the asynchronous state object. 
     Socket handler = (Socket)ar.AsyncState; 
     SocketError error; 
     // Read data from the client socket. 
     int bytesRead = handler.EndReceive(ar, out error); 

     if (error == SocketError.Success) 
     { 
      if (bytesRead > 0) 
      { 
       HandleBuff(bytesRead, buffer); 
       handler.BeginReceive(buffer, 0, receivedDataSize, 
         SocketFlags.None, new AsyncCallback(ReadCallback), handler); 
      } 
      else 
      { 
       handler.Disconnect(true); 
       INSTANCE.StartSocket(); 
      } 
     } 
     else if (error == SocketError.Shutdown || error == SocketError.ConnectionReset) 
     { 
      INSTANCE.StartSocket(); 
     } 
    } 

    public static string InitECI(int port, DoWorkEventHandler commandHandler) 
    { 
     if (INSTANCE == null) 
     { 
      INSTANCE = new ECIMain(); 
      INSTANCE.port = port; 
      onCommand += commandHandler; 
      IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); 
      IPAddress ipAddress = ipHostInfo.AddressList 
        .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork); 
      IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); 
      INSTANCE.ip = ipAddress.ToString(); 
      try 
      { 
       INSTANCE.socket.Bind(localEndPoint); 
      } 
      catch (System.Net.Sockets.SocketException e) 
      { 
       if (e.SocketErrorCode == System.Net.Sockets 
             .SocketError.AddressAlreadyInUse) 
       { 
        //INSTANCE.socket.Bind(localEndPoint); 
       } 
       throw e; 
      } 
      INSTANCE.StartSocket(); 
     } 
     return INSTANCE.ip; 
    } 

    public static void ShutDownECI() 
    { 
     if(INSTANCE.socket.Connected) 
      INSTANCE.socket.Disconnect(false); 
     INSTANCE.socket.Close(); 
    } 
} 

回答

0

當使用TCP協議棧(發送或接收),我們必須看看堆棧它自己的系統,這是防彈,而且運作非常好......大多數這類問題的處理事實即應用層能夠輕鬆地根據需要啓動儘可能多的異步操作,但這並不意味着TCP堆棧將變得更快,特別是如果它不堪重負的話。這意味着它會盡可能排隊並處理任務。

被壓倒的堆棧的症狀之一是通過Netstat命令可視化存在的許多半會話狀態。任何具有「等待」一詞的內容都是半個狀態的指標。這發生在一方發佈數據包但另一方不立即響應時發生。從那裏開始,所有這一切都是艱難的,因爲TCP開始運行,並試圖通過重新發送相同的數據包來保持會話活躍。將此數乘以活動會話的數量,以及在超時之前每個數據包TCP重試次數高達10次的事實,您可以看到這是堆棧需要的最後一件事。

您的情況可能是網絡流量超過單個網絡適配器的容量。這通常通過添加更多網卡並使用其他方式來進行負載平衡來解決。其中一種方法就是他們稱之爲循環法的DNS,它是最便宜的。另一種方式是F5設備。

底線,這聽起來像你的網絡適配器正在被淹沒。

這裏有幾件事要檢查電線的兩側。

  • 當演出開始時,所有插座都完全關閉嗎?
  • 您是否能夠運行網絡監視器來查看總體負載...您通常希望在任何單個網絡適配器上的利用率達到60%或更低。
  • 如果你的負荷過高,那麼你可以跟DNS人關於使用循環賽,並以另一種卡插入同一臺服務器(這將有不同的地址)
  • 有時是由於缺乏數據的壓縮被送到電線上。您也可以調查壓縮技術。
  • 有時候交換機會變壞,從而導致MAC-MAC連接能力。
  • 錯誤的路由器配置可以允許從不同的接入點重新傳輸線路。
  • 配置錯誤的服務器也可能會傳播過多的噪音(總垃圾)
  • 無線接入點臭名昭着,它們可能也是噪聲源。

找到這類問題的根源有很多,但希望其中的一些想法能幫助您。