आपको एक एसिंक्रोनस सर्वलेट की आवश्यकता है लेकिन आपको बाहरी टोकन जनरेटर को एसिंक्रोनस HTTP कॉल की भी आवश्यकता है। यदि आप अभी भी प्रति टोकन अनुरोध पर एक थ्रेड बनाते हैं तो आपको थ्रेड पूल के साथ सर्वलेट से एक्जिक्यूटर्स सर्विस पर अनुरोधों को पास करके कुछ हासिल नहीं होगा। आपको HTTP अनुरोधों से थ्रेड को कम करना होगा ताकि एक थ्रेड एकाधिक HTTP अनुरोधों को संभाल सके। यह अपाचे Asynch HttpClient या Async Http Client जैसे एसिंक्रोनस HTTP क्लाइंट के साथ हासिल किया जा सकता है।
सबसे पहले आप यह एक
public class ProxyService extends HttpServlet {
private CloseableHttpAsyncClient httpClient;
@Override
public void init() throws ServletException {
httpClient = HttpAsyncClients.custom().
setMaxConnTotal(Integer.parseInt(getInitParameter("maxtotalconnections"))).
setMaxConnPerRoute(Integer.parseInt(getInitParameter("maxconnectionsperroute"))).
build();
httpClient.start();
}
@Override
public void destroy() {
try {
httpClient.close();
} catch (IOException e) { }
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
AsyncContext asyncCtx = request.startAsync(request, response);
asyncCtx.setTimeout(ExternalServiceMock.TIMEOUT_SECONDS * ExternalServiceMock.K);
ResponseListener listener = new ResponseListener();
asyncCtx.addListener(listener);
Future<String> result = httpClient.execute(HttpAsyncMethods.createGet(getInitParameter("serviceurl")), new ResponseConsumer(asyncCtx), null);
}
}
यह सर्वलेट अपाचे Asynch HttpClient का उपयोग कर एक अतुल्यकालिक HTTP कॉल करता है की तरह एक अतुल्यकालिक सर्वलेट बनाना होगा। ध्यान दें कि आप प्रति मार्ग अधिकतम कनेक्शन कॉन्फ़िगर करना चाहते हैं क्योंकि आरएफसी 2616 spec के अनुसार HttpAsyncClient केवल डिफ़ॉल्ट रूप से एक ही मेजबान के अधिकतम दो समवर्ती कनेक्शनों को अनुमति देगा। और ऐसे कई अन्य विकल्प हैं जिन्हें आप HttpAsyncClient configuration में दिखाए गए अनुसार कॉन्फ़िगर कर सकते हैं। HttpAsyncClient बनाने के लिए महंगा है, इसलिए आप प्रत्येक जीईटी ऑपरेशन पर इसका एक इंस्टालेशन नहीं बनाना चाहते हैं।
एक श्रोता AsyncContext से जुड़ा हुआ है, यह श्रोता केवल टाइमआउट को संभालने के लिए ऊपर दिए गए उदाहरण में उपयोग किया जाता है।
public class ResponseListener implements AsyncListener {
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
@Override
public void onComplete(AsyncEvent event) throws IOException {
}
@Override
public void onError(AsyncEvent event) throws IOException {
event.getAsyncContext().getResponse().getWriter().print("error:");
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
event.getAsyncContext().getResponse().getWriter().print("timeout:");
}
}
फिर आपको HTTP क्लाइंट के लिए उपभोक्ता की आवश्यकता है। यह उपभोक्ता complete()
पर कॉल करके AsyncContext को सूचित करता है जब buildResult()
को कॉलर ProxyService
सर्वलेट पर Future<String>
वापस करने के चरण के रूप में HttpClient द्वारा आंतरिक रूप से निष्पादित किया जाता है।
public class ResponseConsumer extends AsyncCharConsumer<String> {
private int responseCode;
private StringBuilder responseBuffer;
private AsyncContext asyncCtx;
public ResponseConsumer(AsyncContext asyncCtx) {
this.responseBuffer = new StringBuilder();
this.asyncCtx = asyncCtx;
}
@Override
protected void releaseResources() { }
@Override
protected String buildResult(final HttpContext context) {
try {
PrintWriter responseWriter = asyncCtx.getResponse().getWriter();
switch (responseCode) {
case javax.servlet.http.HttpServletResponse.SC_OK:
responseWriter.print("success:" + responseBuffer.toString());
break;
default:
responseWriter.print("error:" + responseBuffer.toString());
}
} catch (IOException e) { }
asyncCtx.complete();
return responseBuffer.toString();
}
@Override
protected void onCharReceived(CharBuffer buffer, IOControl ioc) throws IOException {
while (buffer.hasRemaining())
responseBuffer.append(buffer.get());
}
@Override
protected void onResponseReceived(HttpResponse response) throws HttpException, IOException {
responseCode = response.getStatusLine().getStatusCode();
}
}
ProxyService सर्वलेट के लिए web.xml विन्यास की तरह
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0" metadata-complete="true">
<display-name>asyncservlet-demo</display-name>
<servlet>
<servlet-name>External Service Mock</servlet-name>
<servlet-class>ExternalServiceMock</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Proxy Service</servlet-name>
<servlet-class>ProxyService</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
<init-param>
<param-name>maxtotalconnections</param-name>
<param-value>200</param-value>
</init-param>
<init-param>
<param-name>maxconnectionsperroute</param-name>
<param-value>4</param-value>
</init-param>
<init-param>
<param-name>serviceurl</param-name>
<param-value>http://127.0.0.1:8080/asyncservlet/externalservicemock</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>External Service Mock</servlet-name>
<url-pattern>/externalservicemock</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Proxy Service</servlet-name>
<url-pattern>/proxyservice</url-pattern>
</servlet-mapping>
</web-app>
और सेकंड में देरी से टोकन जनरेटर के लिए एक नकली सर्वलेट हो सकता है हो सकता है:
public class ExternalServiceMock extends HttpServlet{
public static final int TIMEOUT_SECONDS = 13;
public static final long K = 1000l;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Random rnd = new Random();
try {
Thread.sleep(rnd.nextInt(TIMEOUT_SECONDS) * K);
} catch (InterruptedException e) { }
final byte[] token = String.format("%10d", Math.abs(rnd.nextLong())).getBytes(ISO_8859_1);
response.setContentType("text/plain");
response.setCharacterEncoding(ISO_8859_1.name());
response.setContentLength(token.length);
response.getOutputStream().write(token);
}
}
आप कर सकते हैं fully working example at GitHub प्राप्त करें।
आपने कहा "* टोकन पीढ़ी की प्रक्रिया के दौरान प्रति सेकंड आने वाले अनुरोधों में से लगभग 80% इंतजार करने की आवश्यकता होगी। *", यह सभी के लिए स्पष्ट नहीं है कि इन 80% आने वाले अनुरोध आपके आवेदन के आने वाले अनुरोध हैं या अनुरोध है कि आपने टोकन पीढ़ी के लिए तीसरे पक्ष के सिस्टम को भेजा है। मुझे लगता है कि आपको अपने पूरे उत्तर में यह स्पष्ट करने की जरूरत है कि जब आप किस चीज के बारे में बात कर रहे हैं, क्योंकि जैसा कि मैंने कहा था कि यह सभी के लिए स्पष्ट नहीं हो सकता है, कृपया स्पष्ट करें और आपके पास समाधान प्राप्त करने की संभावना अधिक हो सकती है। – hagrawal
@ हाग्रावल इनकमिंग अनुरोधों का 80% तीसरे पक्ष की प्रतीक्षा कर रहे हैं। –