java जर्सी webservice फ़ाइल डाउनलोड करने और ग्राहक को उत्तर देने के लिए स्केलेबल दृष्टिकोण



web-services jersey (1)

क्लाइंट साइड एसिंक अनुरोध, आपके उपयोग केस के लिए बहुत कुछ करने वाला नहीं है। मामलों का उपयोग "आग और भूल" के लिए यह अधिक मतलब है आप क्या कर सकते हैं, हालांकि क्लाइंट से सिर्फ InputStream प्राप्त हो सकता है और परिणाम स्ट्रीम करने के लिए सर्वर साइड StreamingResource InputStream साथ मिश्रण करें। सर्वर डेटा भेजना शुरू करेगा क्योंकि यह अन्य दूरस्थ संसाधन से आ रहा है।

नीचे एक उदाहरण है "/file" अंत बिंदु डमी रिमोट संसाधन है जो फ़ाइल को कार्य करता है। "/client" अंत बिंदु यह खपत करता है

@Path("stream")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class ClientStreamingResource {

    private static final String INFILE = "Some File";

    @GET
    @Path("file")
    public Response fileEndpoint() {
        final File file = new File(INFILE);
        final StreamingOutput output = new StreamingOutput() {
            @Override
            public void write(OutputStream out) {

                try (FileInputStream in = new FileInputStream(file)) {
                    byte[] buf = new byte[512];
                    int len;
                    while ((len = in.read(buf)) != -1) {
                        out.write(buf, 0, len);
                        out.flush();
                        System.out.println("---- wrote 512 bytes file ----");
                    }
                } catch (IOException ex) {
                    throw new InternalServerErrorException(ex);
                }
            }
        };
        return Response.ok(output)
                .header(HttpHeaders.CONTENT_LENGTH, file.length())
                .build();
    }

    @GET
    @Path("client")
    public void clientEndpoint(@Suspended final AsyncResponse asyncResponse) {
        final Client client = ClientBuilder.newClient();
        final WebTarget target = client.target("http://localhost:8080/stream/file");
        final Response clientResponse = target.request().get();

        final StreamingOutput output = new StreamingOutput() {
            @Override
            public void write(OutputStream out) {
                try (final InputStream entityStream = clientResponse.readEntity(InputStream.class)) {
                    byte[] buf = new byte[512];
                    int len;
                    while ((len = entityStream.read(buf)) != -1) {
                        out.write(buf, 0, len);
                        out.flush();
                        System.out.println("---- wrote 512 bytes client ----");
                    }
                } catch (IOException ex) {
                    throw new InternalServerErrorException(ex);
                }
            }
        };
        ResponseBuilder responseBuilder = Response.ok(output);
        if (clientResponse.getHeaderString("Content-Length") != null) {
            responseBuilder.header("Content-Length", clientResponse.getHeaderString("Content-Length"));
        }
        new Thread(() -> {
            asyncResponse.resume(responseBuilder.build());
        }).start();
    }
}

मैंने अनुरोध करने के लिए cURL का इस्तेमाल किया, और कमांड लाइन से उदाहरण को चलाने में सक्षम होने के लिए jetty-maven-plugin का उपयोग किया। जब आप इसे चलाते हैं, और अनुरोध करते हैं, आपको सर्वर लॉगिंग देखना चाहिए

---- wrote 512 bytes file ----
---- wrote 512 bytes file ----
---- wrote 512 bytes client ----
---- wrote 512 bytes file ----
---- wrote 512 bytes client ----
---- wrote 512 bytes file ----
---- wrote 512 bytes client ----
---- wrote 512 bytes file ----
---- wrote 512 bytes client ----
...

जबकि cURL ग्राहक परिणाम का ट्रैक रखते हुए है

इस से दूर करने का मुद्दा यह है कि "रिमोट सर्वर" लॉगिंग एक ही समय हो रहा है क्योंकि क्लाइंट संसाधन लॉगिंग हो रहा है। यह दर्शाता है कि क्लाइंट पूरी फ़ाइल प्राप्त करने के लिए प्रतीक्षा नहीं करता है। जैसे ही उन्हें प्राप्त करना शुरू होता है, उतनी ही बाइट्स बाहर भेजना शुरू होता है।

उदाहरण के बारे में ध्यान देने वाली कुछ चीजें:

  • मैंने एक छोटा सा बफर आकार (512) का इस्तेमाल किया क्योंकि मैं एक छोटी (1 एमबी) फाइल के साथ परीक्षण कर रहा था मैं वास्तव में परीक्षण के लिए एक बड़ी फ़ाइल के लिए इंतजार नहीं करना चाहता था लेकिन मैं कल्पना करता हूं कि बड़ी फ़ाइलों को केवल वही काम करना चाहिए। बेशक आप बफर आकार को कुछ बड़े आकार में बढ़ाना चाहते हैं।

  • छोटे बफ़र आकार का उपयोग करने के लिए, आपको जर्सी प्रॉपर्टी ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER को 0 से सेट करना होगा। कारण यह है कि जर्सी 8192 के आकार के आंतरिक बफ़र में रहता है, जिससे डेटा की मेरी 512 बाइट मात्रा में फ्लश नहीं होने के कारण 8192 तक बाइट बफर थे। इसलिए मैंने इसे अक्षम कर दिया।

  • AsyncResponse का उपयोग करते AsyncResponse , आपको दूसरे थ्रेड का उपयोग करना चाहिए, जैसा मैंने किया था यद्यपि आप स्पष्ट रूप से धागे बनाने के बजाय निष्पादक का उपयोग करना चाह सकते हैं। यदि आप किसी अन्य थ्रेड का उपयोग नहीं करते हैं, तो आप अभी भी कंटेनर के थ्रेड पूल से धागे को पकड़ रहे हैं।

अद्यतन करें

अपने खुद के थ्रेड्स / निष्पादक को प्रबंधित करने के बजाय, आप @ManagedAsync साथ क्लाइंट संसाधन को एनोटेट कर सकते हैं, और जर्सी को थ्रेड्स प्रबंधित करने दें

@ManagedAsync
@GET
@Path("client")
public void clientEndpoint(@Suspended final AsyncResponse asyncResponse) {
    ...
    asyncResponse.resume(responseBuilder.build());
}

मुझे जर्सी के साथ एक webservice बनाने की आवश्यकता है जो किसी अन्य सेवा से बड़ी फ़ाइल डाउनलोड करता है और क्लाइंट को देता है। मैं जर्सी को कुछ बाइट्स को बफर में पढ़ने और उन बाइट को क्लाइंट सॉकेट में लिखना चाहूंगा।

मैं इसे गैर अवरुद्ध I / O का उपयोग करना चाहता हूं ताकि मैं थ्रेड को व्यस्त न रख सकूं। (यह हासिल नहीं किया जा सका)

    @GET
    @Path("mypath")
    public void getFile(final @Suspended AsyncResponse res) {
        Client client = ClientBuilder.newClient();
        WebTarget t = client.target("http://webserviceURL");
        t.request()
            .header("some header", "value for header")
                .async().get(new InvocationCallback<byte[]>(){

            public void completed(byte[] response) {
                res.resume(response);
            }

            public void failed(Throwable throwable) {
                res.resume(throwable.getMessage());
                throwable.printStackTrace();
                //reply with error
            }

        });
    }

अब तक मुझे यह कोड है और मेरा मानना ​​है कि जर्सी पूरी फाइल डाउनलोड करेगा और फिर इसे ग्राहक को लिख देगा जो कि मैं क्या करना चाहता हूं। कोई विचार??





nonblocking