2009-12-10 12 views
7

हम एक आरईएसटी एपीआई लागू करने के लिए HTTPClient का उपयोग कर रहे हैं।स्ट्रीम बनाम स्ट्रिंग के रूप में इनपुट पढ़ने के लिए यह अधिक मेमोरी कुशल क्यों है?

Dec 9, 2009 7:41:11 PM org.apache.commons.httpclient.HttpMethodBase getResponseBody 
WARNING: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended. 

docs पर जाने के कहने के लिए:

method = new PostMethod(url); 
HttpClient client = new HttpClient(); 
int statusCode = client.executeMethod(method); 
String responseBody = method.getResponseBodyAsString(); 

जब हम ऐसा करते हैं तो हम इस चेतावनी मिलती है:

हम सर्वर प्रतिक्रिया का उपयोग कर पढ़ रहे हैं

HttpClient कुशल अनुरोध/प्रतिक्रिया शरीर स्ट्रीमिंग करने में सक्षम है। बड़ी इकाइयों को स्मृति में buffered किए बिना सबमिट या प्राप्त किया जा सकता है। यह विशेष रूप से महत्वपूर्ण है यदि एकाधिक HTTP विधियों को समवर्ती रूप से निष्पादित किया जा सकता है। स्ट्रिंग्स या बाइट सरणी जैसे इकाइयों से निपटने के लिए सुविधाजनक विधियां हैं, उनका उपयोग निराश है। जब तक सावधानीपूर्वक उपयोग नहीं किया जाता है, तो वे आसानी से मेमोरी स्थितियों से बाहर निकल सकते हैं, क्योंकि वे स्मृति में पूर्ण इकाई का बफरिंग करते हैं।

तो मेरे सवाल है, यदि आप एक स्ट्रिंग के रूप में पूरा प्रतिक्रिया की जरूरत है (यानी: एक DB में स्टोर करने के लिए, या डोम का उपयोग कर पार्स करने के लिए), कारण है कि यह अधिक स्मृति कुशल एक धारा का उपयोग करने के लिए है?

उत्तर

13

यह एक स्ट्रिंग के रूप में पूरे इकाई हो रही के बजाय एक धारा का उपयोग करने के क्योंकि बाद इसका मतलब है कि

  1. प्रतिक्रिया की सारी सामग्री को पढ़ने के लिए इससे पहले कि वे अपने कोड को वापस किया जा सकता की जरूरत है और अधिक कुशल है , और
  2. नियंत्रण तब तक आपके कोड पर वापस नहीं किया जा सकता जब तक कि संपूर्ण प्रतिक्रिया सर्वर द्वारा भेजी नहीं जाती है।

यदि आपने प्रतिक्रिया के रूप में प्रतिक्रिया को संसाधित किया है, तो आप वास्तव में क्या कर रहे हैं यह एक समय में एन बाइट्स को संसाधित कर रहा है। इसका मतलब यह है कि आप पहले प्रतिक्रिया खंड को संसाधित करना शुरू कर सकते हैं जबकि रिमोट सर्वर अभी भी डेटा के अगले खंड को वापस भेज रहा है। इसलिए यह पर पहुंच विधि के रूप में अधिक समझ में आता है यदि आपका उपयोग-केस आपको प्राप्त होने वाले डेटा को संसाधित करने की अनुमति देता है।

यदि आपको किसी भी कारण से स्ट्रिंग के रूप में पूरी प्रतिक्रिया की आवश्यकता है, तो स्ट्रीम विधि की सभी क्षमताओं से आपको कोई असर नहीं पड़ता है - क्योंकि यदि आप टुकड़ों में प्रतिक्रिया पढ़ते हैं, तो भी आपको प्रतीक्षा करनी होगी पूरी प्रतिक्रिया - और यह सब एक स्ट्रिंग में निहित है - इससे पहले कि आप इसे संसाधित कर सकें।

स्ट्रीम का उपयोग करने की दक्षता केवल आपके लिए उपलब्ध है यदि आपके पास उपयोग-मामला है जहां आप पूरे प्रतिक्रिया शरीर से पहले प्रतिक्रिया को संसाधित करना शुरू कर सकते हैं।

4

पूरी प्रक्रिया अधिक मेमोरी कुशल नहीं है। यदि आप किसी स्ट्रीम से पढ़ते हैं और इसे स्ट्रिंग में डालते हैं तो आप प्रक्रिया को दो हिस्सों में अलग कर रहे हैं ताकि HttpClient क्लास इसे नोटिस न करे।

यदि आपको वास्तव में पूरी स्ट्रिंग की आवश्यकता है तो आप चेतावनी को अनदेखा कर सकते हैं। यह सुनिश्चित करने के लिए आप पर निर्भर है कि यह प्रति अनुरोध बहुत अधिक स्मृति का उपयोग नहीं करता है, ताकि सर्वर को आसानी से डीओएस हमले से लाया जा सके।

1

आपका प्रश्न इस बिंदु को भ्रमित करता है।

अगर आपको निश्चित स्ट्रिंग के रूप में पूरे प्रतिक्रिया की जरूरत तो है कि,

लेकिन यदि आप सब पर इसके साथ प्राप्त कर सकते हैं, नदियों का उपयोग करते हैं।

जब आप स्ट्रिंग में पूरी प्रतिक्रिया लोड करते हैं, तो संपूर्ण प्रतिक्रिया निकाय एक समय में स्मृति में मौजूद होता है।

धाराओं का उपयोग करके, प्रतिक्रिया का केवल एक छोटा सा हिस्सा स्मृति में एक समय में आयोजित किया जाता है।

प्रलेखन कह रहा है कि, विशेष रूप से एक साथ कई बड़े अनुरोधों के साथ, पूरे अनुरोध निकाय को स्ट्रिंग में लोड करने के लिए बहुत सारी मेमोरी की आवश्यकता होगी।

0

यदि आप org.w3c.Document (या बेहतर अभी तक, org.jdom.Document) में पार्स कर रहे हैं, तो स्ट्रीम का सीधे उपयोग करना वास्तव में आसान है। पूर्व:

org.apache.http.HttpResponse hr = httpClient.execute(httpRequest); 
org.apache.http.HttpEntity he = hr.getEntity(); 
org.jdom.input.SAXBuilder builder = new SAXBuilder(); 
org.jdom.Document document = builder.build(he.getContent()); 
संबंधित मुद्दे