2015-10-13 11 views
10

में पुन: उपयोग JAX आरएस ग्राहक,(resteasy के साथ) मल्टी-थ्रेडेड वातावरण प्रलेखन के अनुसार

"ग्राहक भारी वजन वस्तुओं है कि क्लाइंट-साइड संचार बुनियादी सुविधाओं का प्रबंधन कर रहे हैं। प्रारंभ करने के साथ ही के निपटान एक क्लाइंट उदाहरण एक नहीं बल्कि महंगा ऑपरेशन हो सकता है। इसलिए यह आवेदन में ग्राहक उदाहरणों में से केवल एक छोटी संख्या का निर्माण करने की सलाह दी है। "

ठीक है, मैं ग्राहकों का ही है और वेब कैश करने के लिए कोशिश कर रहा हूँ लक्ष्य उदाहरणों एक स्थिर चर में, someMethod() मल्टी-थ्रेडेड वातावरण में शुरू हो जाती है:

private static Client client = ClientBuilder.newClient(); 
private static WebTarget webTarget = client.target("someBaseUrl"); 
... 
public static String someMethod(String arg1, String arg2) 
{ 
    WebTarget target = entrTarget.queryParam("arg1", arg1).queryParam("arg2", arg2); 
    Response response = target.request().get(); 
    final String result = response.readEntity(String.class); 
    response.close(); 
    return result; 
} 

लेकिन कभी कभी (हमेशा) मैं एक अपवाद मिल रही है:

BasicClientConnManager का अमान्य उपयोग: कनेक्शन अभी भी आवंटित। किसी अन्य को आवंटित करने से पहले कनेक्शन को रिलीज़ करना सुनिश्चित करें।

क्लाइंट/वेबटाइटल का पुन: उपयोग/कैश किया जा सकता है? क्या यह जेएक्स आरएस क्लाइंट एपीआई के साथ संभव है? या मुझे कुछ ढांचे-विशिष्ट विशेषताओं (रेस्टसी/जर्सी) का उपयोग करना होगा क्या आप कुछ उदाहरण या दस्तावेज़ीकरण प्रदान कर सकते हैं?

+0

की संभावित डुप्लिकेट [JAX-आरएस क्लाइंट थ्रेड सुरक्षित है] (http://stackoverflow.com/questions/24700798/is-jax-rs-client-thread-safe) – tddmonkey

उत्तर

5

आपका कार्यान्वयन थ्रेड-सुरक्षित नहीं है। जब दो धागे someMethod तक पहुंचते हैं, तो वे एक ही समय में Client साझा कर रहे हैं और कोई दूसरा अनुरोध करने का प्रयास करेगा जबकि पहला खाता समाप्त नहीं होगा।

  • Client और WebTarget मैन्युअल के लिए उपयोग सिंक्रनाइज़:

    आपके पास दो विकल्प।

  • कंटेनर @javax.ejb.Singleton के साथ संलग्न प्रकार को एनोटेट करके समेकन का प्रबंधन करने दें जो थ्रेड सुरक्षा की गारंटी देता है। एक कंटेनर प्रबंधित परिवेश में (EJB specification के अध्याय 4.8.5 देखना)

तो someMethod मैं दूसरा दृष्टिकोण का प्रयोग करेंगे।

3

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

दूसरा, यदि आप रीस्टेसी का उपयोग कर रहे हैं, तो आप अपने प्रोजेक्ट में रीस्टेसी क्लाइंट के लिए प्रदान की गई निर्भरता जोड़ सकते हैं। Gradle में उदाहरण:

 ResteasyClientBuilder builder = new ResteasyClientBuilder(); 
     builder.connectionPoolSize(200); 

, इस RestEasy द्वारा स्वचालित रूप से सेट किया गया है maxPooledPerRoute स्थापित करने के लिए कोई जरूरत नहीं है (RestEasyClientBuilder वर्ग स्रोत में पाया जा सकता:

provided 'org.jboss.resteasy:resteasy-client:3.0.14.Final' 

उसके बाद, आप इस तरह अपने कनेक्शन बना सकते हैं कोड)।

जब आप कनेक्शन पुलसाइज सेट करते हैं, तो क्लाइंट का पुन: उपयोग होने पर आपको अब त्रुटि नहीं मिलेगी और आप खुशी से उन्हें पूरे एप्लिकेशन में फिर से उपयोग कर सकते हैं। मैंने कई परियोजनाओं पर इस समाधान की कोशिश की है और यह वास्तव में अच्छी तरह से काम करता है।लेकिन जब आप अपने एप्लिकेशन को एक गैर-आराम कंटेनर (जैसे ग्लासफ़िश) पर तैनात करते हैं, तो आपका कोड काम नहीं करेगा और आपको क्लाइंटबिल्डर क्लास का फिर से उपयोग करना होगा।

5

के बाद से यह समस्या अभी भी लिख (संस्करण 3.0.x) के समय में खुला है RESTEASY: deprecated Apache classes cleanup

आप आप ग्राहक resteasy बनाने के लिए बजाय नए, गैर पदावनत वर्गों का उपयोग करने के गहरे जा सकते हैं।

// This will create a threadsafe JAX-RS client using pooled connections. 
// Per default this implementation will create no more than than 2 
// concurrent connections per given route and no more 20 connections in 
// total. (see javadoc of PoolingHttpClientConnectionManager) 
PoolingHttpClientConnectionManager cm = 
     new PoolingHttpClientConnectionManager(); 

CloseableHttpClient closeableHttpClient = 
     HttpClientBuilder.create().setConnectionManager(cm).build(); 
ApacheHttpClient4Engine engine = 
     new ApacheHttpClient4Engine(closeableHttpClient); 
return new ResteasyClientBuilder().httpEngine(engine).build(); 

इसके अलावा सुनिश्चित करें कि आप एक कॉल करने के बाद कनेक्शन जारी करते हैं: आप यह भी कि कैसे आप पूल आदि होने की

यहाँ मैं क्या किया है चाहता हूँ पर अधिक नियंत्रण होगा। कॉलिंग respond.close() आपके लिए ऐसा करेगा, इसलिए शायद इसे अंत में ब्लॉक में डाल दें।

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