Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Streaming proxy of content using jetty and jetty-client with end to end flow control

> On Sep 26, 2017, at 4:51 PM, Joakim Erdfelt <joakim@xxxxxxxxxxx> wrote:
> 
> This is what our org.eclipse.jetty.proxy.AsyncProxyServlet already does.
> 
> https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java
> 
> Why write your own?

Because I did not know this existed :)

Also, I do nontrivial rewriting of the request (this is not at all a transparent proxy,
it is quite invasive) so I will probably not be able to use the code as is.

But it probably answers my questions and just needs adaptation, so thank you very much
for the pointer.

(This is a lot of complex code!  Asynchronous programming is hard...)

> 
> 
> Joakim Erdfelt / joakim@xxxxxxxxxxx
> 
> On Tue, Sep 26, 2017 at 4:47 PM, Steven Schlansker <stevenschlansker@xxxxxxxxx> wrote:
> Hi jetty-users,
> 
> Still working on my http proxy :)
> Now I'm trying to make sure I've got the content proxying working correctly
> using both asynchronous servlet as well as NIO nonblocking writing.
> 
> Because both the server and client are pushing notifications at me, I believe
> I need to implement some sort of transfer queue.  I was hoping that I'd end up
> in a push-pull situation but ServletOutputStream calls you via a WriteListener
> and Jetty-Client calls you via a Response.ContentListener.
> 
> Unfortunately, this leaves me in a position where I don't know how to get flow
> control working.  The client pushes data at me and I don't have a way to push back.
> 
> My current pesudocoded approach:
> 
> Deque<Runnable> writes;
> volatile boolean complete = false;
> 
> asyncCtx = httpResponse.startAsync();
> out = (HttpOutput) httpResponse.getOutputStream();
> 
> writeListener = new WriteListener() {
>     synchronized void onWritePossible() { // avoid re-entrance with 'synchronized'
>         while(out.isReady()) {
>             pending = writes.removeFirst();
>             if (pending != null) {
>                 pending.run();
>             } else if (complete && writes.isEmpty()) {
>                 asyncCtx.complete();
>             } else {
>                 return;
>             }
>         }
>     }
> };
> 
> out.setWriteListener(writeListener);
> 
> proxyClientRequest.send(new Response.ContentListener() {
>     void onContent(ByteBuffer buf, Callback complete) {
>         writes.push(() -> {
>             out.write(buf);
>             complete.succeeded();
>         };
>         writeListener.onWritePossible();  // See if we can write it immediately
>     }
> 
>     void onComplete() {
>         complete = true;
>         writeListener.onWritePossible();
>     }
> });
> 
> This has the nice property where I don't copy buffers, just keep them in a queue
> of pending writes -- but I worry that in the case of a slow reader, Jetty Client
> will continue onContent-pushing buffers at me until I run out of memory.
> 
> I could instead use the OutputStreamContentProvider and just read from it in the
> WriteListener, which might fix the flow control, but that seems likely to involve
> a number of byte[] copies that I was hoping to avoid.
> 
> What's the right approach to wire up Jetty server to Jetty client with full NIO + Async
> content proxying, without introducing an intermediate transfer buffer that might grow
> without bound?  Am I on the right path or am I missing something?  Thanks for any guidance!
> 
> 
> _______________________________________________
> jetty-users mailing list
> jetty-users@xxxxxxxxxxx
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users
> 
> _______________________________________________
> jetty-users mailing list
> jetty-users@xxxxxxxxxxx
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail


Back to the top