> On Sep 26, 2017, at 5:05 PM, Joakim Erdfelt <[email protected]> wrote: > > modifying the request or response during proxy is also supported out of the > box by the ... > org.eclipse.jetty.proxy.AsyncMiddleManServlet > > https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncMiddleManServlet.java >
This is getting much closer to what I need. The big thing that's missing, we
have a custom
service resolution protocol layered on top of DNS; I have a list of URIs to
attempt
and if there is a failure before the request content is sent (for example,
socket
timeout, no route to host, connection refused) I then want to try the next in
the list
until we have a success or the operation times out.
(Once we write the request, we do not do further retries)
My initial attempt was to implement this as a custom HttpDestination subclass
and
subclass of SocketAddressResolver.Async that returns many InetSocketAddresses;
unfortunately the resolver does not receive the Destination and similarly the
Request gets no knowledge of which address ends up getting picked.
I tried prying open the HttpConversation and HttpExchange objects by the usual
blind downcasts,
but it was seemingly not possible to figure out the actual endpoint selected.
Not knowing the actual destination means we can't log all the information we
want to.
So my current approach is the tried and true "while (keepTrying) {
client.send(...); }"
which is less elegant but then we know the actual URI we try every time :)
The MiddleManServlet takes care of the HTTP proxying beautifully, and you are
correct
that I'd rather not replicate that. But it doesn't look like it does this sort
of
retries, and I'm not sure I can plug in to all the right places to collect the
metrics
and logging data I need. I'll play with it though and maybe with some cleverly
placed
overrides I can get most of it.
>
>
> Joakim Erdfelt / [email protected]
>
> On Tue, Sep 26, 2017 at 5:03 PM, Steven Schlansker
> <[email protected]> wrote:
>
> > On Sep 26, 2017, at 4:51 PM, Joakim Erdfelt <[email protected]> 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 / [email protected]
> >
> > On Tue, Sep 26, 2017 at 4:47 PM, Steven Schlansker
> > <[email protected]> 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
> > [email protected]
> > 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
> > [email protected]
> > 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
> [email protected]
> 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
> [email protected]
> To change your delivery options, retrieve your password, or unsubscribe from
> this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users
signature.asc
Description: Message signed with OpenPGP using GPGMail
_______________________________________________ jetty-users mailing list [email protected] To change your delivery options, retrieve your password, or unsubscribe from this list, visit https://dev.eclipse.org/mailman/listinfo/jetty-users
