2011-06-29 32 views
8

को संभालने का सबसे अच्छा तरीका मेरे पास एक वास्तविक समय ऐप है जो देश भर में कई साइटों के आसपास संपत्तियों को ट्रैक करता है। इस समाधान के हिस्से के रूप में मेरे पास 8 क्लाइंट ऐप्स हैं जो केंद्रीय सर्वर को अपडेट करते हैं।डब्ल्यूसीएफ टाइमआउट

मेरा सवाल यह है कि कभी-कभी ऐप्स केंद्रीय सर्वर से कनेक्शन खो देते हैं और मैं सोच रहा हूं कि इससे निपटने का सबसे अच्छा तरीका क्या है? मुझे पता है कि मैं टाइमआउट से निपटने के लिए अधिकतम प्रेषण/प्राप्त करने के समय को बढ़ा सकता हूं लेकिन सर्वर से कनेक्शन नीचे होने पर भी निपटने के लिए एक सुखद समाधान चाहिए:

उदाहरण के लिए मैं अपनी सेवाओं को इस तरह बुला रहा हूं :

using (var statusRepository = new StatusRepositoryClient.StatusRepositoryClient()) 
{ 
    statusId = statusRepository.GetIdByName(licencePlateSeen.CameraId.ToString()); 
} 

मैं आज़माएं/कैच तो जोड़ने के बारे में सोच रहा था ...

using (var statusRepository = new StatusRepositoryClient.StatusRepositoryClient()) 
{ 
    try 
    { 
     statusId = statusRepository.GetIdByName(licencePlateSeen.CameraId.ToString()); 
    } 
    catch (TimeoutException timeout) 
    { 
     LogMessage(timeout); 
    } 
    catch (CommunicationException comm) 
    { 
     LogMessage(comm); 
    } 
} 

यह इस तरह से मुझे कोड दोहराने के लिए ढेर बिना कोड को फिर से चलाएं करने की अनुमति नहीं निपटने। किसी को भी कोई सुझाव मिला है?

संपादित करें: सिक्सटो सैज़ और उपयोगकर्ता 24601 उत्तरों में एक समग्र समाधान होने पर एक व्यक्तिगत अपवाद स्तर पर टाइमआउट से निपटने से बेहतर है लेकिन ... मैं सोच रहा था कि नीचे मेरी समस्या का समाधान होगा (लेकिन यह एक जोड़ देगा अतिरिक्त कोड त्रुटि हैंडलिंग का टन):

void Method(int statusId) 
{ 
    var statusRepository = new StatusRepositoryClient.StatusRepositoryClient() 

     try 
     { 
     IsServerUp(); 
     statusId = statusRepository.GetIdByName(licencePlateSeen.CameraId.ToString()); 
     statusRepository.Close(); 
     }    
     catch (Exception ex) 
     { 
      statusRepository.Abort(); 

      if (ex is TimeoutException || ex is CommunicationException) 
      { 
       LogMessage(timeout); 
       Method(statusId); 
      } 
      else 
      { 
       throw new Exception(ex.Message + ex.InnerException); 
      } 
     } 

    } 
} 

bool IsServerUp() 
{ 
    var x = new Ping(); 
    var reply = x.Send(IPAddress.Parse("127.0.0.1")); 

    if (reply == null) 
    { 
     IsServerUp(); 
    } 
    else 
    { 
     if (reply.Status != IPStatus.Success) 
     { 
      IsServerUp(); 
     } 
    } 

    return true; 
} 
+0

आप एक ऐसा फ़ंक्शन लिख सकते हैं जो सर्वर के ऊपर परीक्षण करता है, इस प्रकार आप यह जांच सकते हैं कि सर्वर आपके पास रिपोजिटरी से कनेक्शन बनाने से पहले है या नहीं। सर्वर ऊपर होने तक आप एक नज़र में भी जा सकते हैं। – Jethro

+0

तो एक रिकर्सिव फ़ंक्शन बनाएं जो सर्वर तक तब तक बाहर नहीं निकलता है जब तक कि जारी रहे ... और किसी भी डब्ल्यूसीएफ कॉल से पहले कॉल पॉप करें? मुझे विचार पसंद है और यह ऊपर वर्णित संपादन से कम कोड होगा .. आपका विचार निश्चित रूप से विश्वसनीयता 99% में सुधार करता है लेकिन अगर सर्वर चेक और विधि कॉल के बीच कनेक्शन खो देता है तो मैं कैसे निपटूं? –

+0

@ जेथ्रो: सर्वोत्तम अभ्यास पिंग विधि के खिलाफ सलाह देते हैं। यहां चर्चा देखें: http://stackoverflow.com/questions/2166356/how-to-check-if-a-wcf-service-is-operational मूलभूत विचार यह है कि टाइमआउट सेवा निर्भरता का परिणाम हो सकता है जो होगा एक पिंग इवेंट में दिखाई नहीं दे रहा है (जैसे एक डब्ल्यूसीएफ सेवा जो डाटाबेस के साथ इंटरैक्ट करता है जहां डेटाबेस टाइमआउट का कारण बनता है) – VoteCoffee

उत्तर

3

स्टार्टर्स के लिए मुझे लगता है कि आपका डब्ल्यूसीएफ त्रुटि प्रबंधन गलत है। यह

var statusRepository = new StatusRepositoryClient.StatusRepositoryClient(); 
try 
{ 
    statusId = statusRepository.GetIdByName(licencePlateSeen.CameraId.ToString()); 
    statusRepository.Close() 
} 
catch(Exception e) 
{ 
    statusRepository.Abort(); 
    LogMessage(e); 
    throw; //I would do this to let user know. 
} 

मैं उपयोगकर्ता को समस्या के बारे में जानने के लिए त्रुटि को फिर से फेंक दूंगा।

+0

कथन कलेक्टर को स्वचालित रूप से आग लगने पर बंद करने/बंद करने से मुझे क्या फायदा होता है जब उपयोग कथन समाप्त हो जाते हैं? –

+1

डब्ल्यूसीएफ में निपटान पैटर्न कार्यान्वयन के बारे में पढ़ने के लिए और आपको कभी भी उपयोग की जाने वाली स्टेटमेंट का उपयोग क्यों नहीं करना चाहिए, इसके साथ [एक अच्छी पोस्ट] (http://geekswithblogs.net/DavidBarrett/archive/2007/11/22/117058.aspx) है यह, –

1

अपने अपवाद हैंडलिंग को डिजाइन करने से पहले, यह सुनिश्चित करने का एक महत्वपूर्ण निर्णय यह है कि क्या आप ग्राहक द्वारा भेजे गए प्रत्येक संदेश की गारंटीकृत डिलीवरी चाहते हैं या सेवा के लिए कुछ खोना ठीक है। guaranteed delivery, के लिए सबसे अच्छा अंतर्निहित समाधान netMsmq बाइंडिंग मानता है कि क्लाइंट को इसका समर्थन करने के लिए कॉन्फ़िगर किया जा सकता है। अन्यथा, एक हल्के वजन reliable messaging capability डब्ल्यूसीएफ में बनाया गया है। आप सर्वर की पुष्टि करने के लिए एक खरगोश की मांद नीचे जा रहा हो जाएगा अगर आप अपवाद संचालन के माध्यम से विशुद्ध रूप से संदेश वितरण को संभालने के लिए कोशिश ... :)

+0

धन्यवाद में देखेंगे –

2

मैं एक दो आयामी दृष्टिकोण है ऊपर:

1) मैं हर 5 सेकंड में सर्वर के लिए 'पिंग' सेट अप किया है। सर्वर 'पोंग' और लोड रेटिंग (कम, मध्यम, उच्च, के साथ प्रतिक्रिया करता है, इसलिए क्लाइंट सर्वर पर अपना भार समायोजित कर सकता है)। यदि ग्राहक को कभी भी पोंग नहीं मिलता है तो यह मानता है कि सर्वर नीचे है (क्योंकि यह सर्वर पर बहुत कम तनाव है - बस सुनो और जवाब दें)।

2) आपके द्वारा पकड़े जाने वाले जैसे यादृच्छिक टाइमआउट सभी सफल कनेक्शन के साथ एक कनेक्शन मॉनिटर क्लास में लॉग इन हैं। इन कॉल कॉलिंग में से एक भी सर्वर पर विचार करने के लिए पर्याप्त नहीं है क्योंकि कुछ बहुत प्रोसेसर भारी हो सकते हैं, या बस बहुत लंबा समय ले सकते हैं। हालांकि, इनमें से एक उच्च पर्याप्त प्रतिशत एप्लिकेशन को टाइमआउट में जाने का कारण बनता है।

मैं भी प्रत्येक कनेक्शन टाइमआउट के लिए एक संदेश नहीं फेंकना चाहता था, क्योंकि यह उन लोगों के लिए अक्सर होता जा रहा था जो गरीब सर्वर का उपयोग करते हैं (या सर्वर के रूप में अपनी प्रयोगशाला में बस कुछ कंप्यूटर झूठ बोलते हैं)। मेरी अधिकांश कॉलों को एक या दो बार याद किया जा सकता है, लेकिन 5 या 6 कॉल गायब होने से स्पष्ट रूप से बाहर निकलना पड़ता है।

जब सर्वर-टाइमआउट स्थिति होती है, तो मैं उपयोगकर्ता के साथ क्या हो रहा है, यह समझाते हुए एक छोटा संवाद बॉक्स फेंक देता हूं।

1

हाय कृपया नीचे मेरा समाधान देखें। कृपया ध्यान दें कि नीचे दिए गए कोड को संकलित नहीं किया गया है, इसलिए कुछ तर्क और टाइपिंग त्रुटियां हो सकती हैं।

bool IsServerUp() 
{ 
    var x = new Ping(); 
    var reply = x.Send(IPAddress.Parse("127.0.0.1")); 

if (reply == null) return false; 

return reply.Status == IPStatus.Success ? true : false; 
} 

int? GetStatusId() 
{ 
try 
{ 
    using (var statusRepository = new StatusRepositoryClient.StatusRepositoryClient()) 
    { 
     return statusRepository.GetIdByName(licencePlateSeen.CameraId.ToString()); 
    } 
}catch(TimeoutException te) 
{ 
    //Log TimeOutException occured 
    return null; 
} 
} 

void GetStatus() 
{ 
try 
{ 
    TimeSpan sleepTime = new TimeSpan(0,0,5); 
    int maxRetries = 10; 

    while(!IsServerUp()) 
    { 
     System.Threading.Thead.Sleep(sleepTime); 
    } 

    int? statusId = null; 
    int retryCount = 0; 

    while (!statusId.HasValue) 
    { 
     statusId = GetStatusId(); 
     retryCount++; 

     if (retryCount > maxRetries) 
      throw new ApplicationException(String.Format("{0} Maximum Retries reached in order to get StatusId", maxRetries)); 
     System.Threading.Thead.Sleep(sleepTime); 
    } 
}catch(Exception ex) 
{ 
    //Log Exception Occured 
} 
} 
संबंधित मुद्दे