2009-02-06 18 views
7

बंद करता है मेरे पास एक सर्वलेट है जो लंबे समय से अनुरोध को संसाधित करता है। ऐसा लगता है कि डूपोस्ट के अंदर लूप में सामान रखने के लिए और प्रतिक्रिया के बाहर लेखक के माध्यम से डेटा भेजें। प्रभावी रूप से क्लाइंट ब्राउज़र में लगातार डेटा जोड़ता है। लेकिन जब ग्राहक क्लाइंट को बंद कर देता है तो समस्याएं ठीक होती हैं। टूटे हुए कनेक्शन के के बावजूद servlet में प्रतिक्रिया का लेखक स्ट्रीम कभी बंद नहीं होता है, इस प्रकार सर्वलेट ब्रोकन कनेक्शन, से अनजान है और बिना किसी त्रुटि के लेखक को डंपिंग डेटा रखें। यह कैसे है? और मैं ब्राउज़र डिस्कनेक्ट के मामले में लंबे अनुरोध प्रसंस्करण का पता लगाने और रद्द कैसे करूं?ब्राउज़र लंबे समय तक प्रसंस्करण रद्द करता है जब ब्राउज़र

मैं प्रतिक्रिया लेखक पर चेक एरर() को चाल करना चाहिए, लेकिन यह काम करने के लिए सीम नहीं है। कोई विचार क्यों?

यह सर्वलेट कोड है जो कभी नहीं बंद हो जाता है:

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
{ 
    HttpSession session = request.getSession(); 
    System.out.println("Session " + session.getId() + " started"); 

    response.setContentType("text/html;charset=UTF-8"); 

    PrintWriter out = response.getWriter(); 
    try 
    { 
     while (!out.checkError()) 
     { 
      try 
      { 
       Thread.sleep(1000); 
      } catch (InterruptedException ex) 
      { 
       ex.printStackTrace(); 
      } 

      Date date = new Date(); 

      // TODO append output to the client browser here 
      out.println("....."); 

      System.out.println("Session " + session.getId() + "data sent at: " + date); 

      out.flush(); 
     //break; // _TEST 
     } 
    } finally 
    { 
     System.out.println("Session " + session.getId() + " finished"); 
     out.close(); 
    } 
} 

धन्यवाद,
माइक

उत्तर

4

इस से निपटने का केवल असली तरीका ब्राउज़र लगातार आपको बता दूँ कि यह अभी भी वहाँ है, हर 5-10 सेकंड कहते हैं। यदि आप कुछ भी सुनने के बिना एक मिनट के लिए जाते हैं, तो आप मानते हैं कि ग्राहक चला गया है और भूल रहा है कि आप क्या कर रहे हैं।

इस लागू करने के लिए कई तरीके हैं:

  • मेटा ताज़ा: क्योंकि यह चिंताजनक है और उपयोगकर्ता के लिए स्पष्ट है मुझे यह पसंद नहीं है,
  • एक आईफ्रेम जो करता है (कम स्पष्ट); या
  • कुछ AJAX तकनीक, जो शायद सबसे अच्छा विकल्प है।

कोई वास्तविक तरीका नहीं है कि आप यह पता लगा सकते हैं कि ग्राहक अभी भी जो भी भेज रहा है उसे पढ़ रहा है। टीसीपी कनेक्शन मरने में समय लगता है और क्लाइंट का मार्ग प्रायः अप्रत्यक्ष होता है (प्रॉक्सी के माध्यम से और आगे) तो इसका पता लगाने के बारे में भूल जाओ।

+0

ऐसा लगता है कि आप सही हैं। मुझे क्लाइंट पक्ष से एसीके भेजने के लिए कुछ मैकेनिज्म होना होगा ताकि यह इंगित किया जा सके कि सर्वर को डेटा भेजना चाहिए। यह दुर्भाग्यपूर्ण और अजीब है क्योंकि http टीसीपी का उपयोग करता है और इस प्रकार कनेक्शन-जागरूक होने का अनुमान लगाता है। – Ma99uS

+0

यह टीसीपी के रूप में HTTP का वर्णन करने के लिए एक गलत नाम है। निश्चित रूप से HTTP प्रोटोकॉल है लेकिन वेब नहीं है (जरूरी)। यूआईडीपी पर सामग्री संचार और वितरित करने वाले स्क्विड कैश पर विचार करें। साथ ही आपका वेब ऐप सामग्री वितरित कर सकता है, कनेक्शन बंद कर सकता है और प्रॉक्सी ब्राउज़र से कनेक्ट हो जाता है। – cletus

+1

क्या इसका मतलब यह है कि यदि आपने वेब ब्राउज़र के माध्यम से बड़ी फ़ाइल डाउनलोड करना शुरू किया है, और आप इसे बंद करने से पहले। सर्वर अभी भी आपको ट्रैफिक या/और सर्वर संसाधनों का उपयोग करके पूरी फाइल भेज देगा? – Ma99uS

1

सर्वलेट में एक आउटपुट बफर है जो वास्तव में ब्राउज़र को डेटा भेजने से पहले भरना होगा। यदि यह बफर भरा नहीं गया है, तो नेटवर्क पर वास्तव में कोई डेटा नहीं भेजा जाता है। जब तक आप नेटवर्क पर डेटा नहीं भेजते, आप नहीं जानते कि कनेक्शन बंद है।

आउटपुट स्ट्रीम या लेखक प्राप्त करने से पहले आप अपनी प्रतिक्रिया ऑब्जेक्ट पर एक विधि को कॉल करके बफर आकार सेट कर सकते हैं।

+0

मैंने प्रतिक्रिया जोड़ने की कोशिश की है .setBufferSize (0); लेकिन ऐसा कोई प्रभाव नहीं प्रतीत होता था। – Ma99uS

+1

आप इसे शून्य पर सेट नहीं कर सकते हैं, आप इसे कुछ छोटे मान पर सेट कर सकते हैं और बफर को लिखने का प्रयास कर सकते हैं। –

1

आप ऐसा कुछ करने की कोशिश कर रहे हैं जो HTTP प्रोटोकॉल द्वारा समर्थित नहीं है। वेब की पूरी प्रकृति अनुरोध/प्रतिक्रिया पर आधारित है।

आपको जो चाहिए उसे अनुकरण करने का एक तरीका अजाक्स का उपयोग करना है। प्रवाह कुछ इस तरह होगा:

  1. ब्राउज़र भेजता है, अजाक्स, 10
  2. सर्वर प्रक्रिया अनुरोध के माध्यम से 1 आइटम के लिए एक अनुरोध, का उपयोग करते हुए निर्माण और के माध्यम से 10
  3. ब्राउज़र 1 से आइटम के साथ प्रतिक्रिया भेज प्रतिक्रिया प्राप्त करता है, पार्स परिणाम, आइटम 1 से 10 तक प्रदर्शित करता है और चरण 1 को दोहराता है, आइटम 11 से 20 का अनुरोध करता है।

यह आर्किटेक्चर क्लाइंट की "उपलब्धता" की जांच करने की आवश्यकता को खत्म कर देगा, और आपके सर्वर साइड घटकों की स्केलेबिलिटी में भी सुधार करेगा।

मुझे उम्मीद है कि यह मदद करता है।

0

java.io.PrintWriter javadoc sez: इस वर्ग में तरीके I/O अपवादों को कभी नहीं फेंकते हैं - इसलिए इसके बजाय javax.servlet.SocketOutputStream (response.getOutputStream()) का उपयोग करें, और आपको अंततः कुछ IOException मिलेगा।

0

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

0

हमें एक ही समस्या थी। हमारे मामले में यह वेबसर्वर था जिसमें ईएसआई सक्षम था (http://www-01.ibm.com/support/docview.wss?uid=swg27015501)। हमने यह देखने के लिए एक टीसीपी डंप किया था कि वहां क्या हुआ और देखा कि आरईएस पैकेज (ब्राउज़र बंद होने के बाद) कभी भी एप्लिकेशन पर वापस नहीं भेजा गया था। वेबसर्वर ने इसे प्राप्त किया लेकिन इसे आगे नहीं भेजा। इसलिए printer.checkError() कभी भी सच नहीं हुआ और प्रिंटर डेटा को फ्लश कर रहा था। इस सुविधा को अक्षम करने के बाद, आरईएस पैकेज को एप्लिकेशन के माध्यम से भेजा गया था और कुछ समय के बाद printer.checkError() सच हो गया। यही कारण है कि मैं आपके प्रश्न पर ठोकर खाई। यह 3 बार भेजता रहता है। इसके बाद यह चेकर() सच हो जाता है।

संबंधित मुद्दे