users@grizzly.java.net

Re: Non-Blocking Read/Write in Proxy

From: Oleksiy Stashok <oleksiy.stashok_at_oracle.com>
Date: Tue, 23 Jun 2015 15:46:35 +0200

Hi Dan,


On 23.06.15 14:34, Daniel Feist wrote:
> Hi Alexey,
>
>> Right, AHC uses different abstractions, for non-blocking AHC feeding you can
>> use NonBlockingFeeder.
>> Please take a look at the sample
>> https://github.com/AsyncHttpClient/async-http-client/blob/1.9.x/src/test/java/com/ning/http/client/async/grizzly/GrizzlyFeedableBodyGeneratorTest.java#L210
> Interesting, I hadn't seen this because there are no concrete
> implementations of this currently being used. So in this case I'd
> need NonBlockingFeeder implementation that understands
> org.glassfish.grizzly.http.io.BinaryNIOInputSource instances. Then
> I'd want to create a FeedableBodyGenerator that uses this feeder and
> set that as the AHC request body. Sound about right?
Yes, BinaryNIOInputSource (or NIOInputStream) could be used to feed the
client request body.

>
>> Yes, this body part is not related to chunking or multipart, it's just a
>> body part Grizzly was able to read from network.
>> Not sure why you'd like to put this into NIOInputStreamImpl, do you want to
>> buffer the response?
> While AHC has infrastructure for feeding a request body, there is no
> such infrastructure for handling responses that I could see. So my
> assumption was that creating a NIOInputStream like i plan to do for
> the grizzly inbound would be the best approach (remember I wanted to
> NIOInputStream is to be able to support existing components that only
> understand InputStreams also). I'd have to do this the first time
> onBodyPartReceived() is invoked only, and then have following
> invocations continue the async transfer. Or is there something in AHC
> to support this that I haevn't seen?
AFAIK AHC doesn't provide anything else, IMO the AHC listener approach
is pretty good and generic solution, you can always wrap it with
something more complicated like NIOInputStream etc.

You can start implementing these parts and once you meet some problem -
pls. share the code - I'll try to help.

Thanks.

WBR,
Alexey.
>
>>> - IN:RESPONSE: I haven't looked at this yet other than considering if
>>> grizzly should consume NIOInputStreamImpl for response or if I'd need
>>> to convert NIOInputStreamImpl to OutputSink etc. Any thoughts?
>> Hmm, potentially we can implement some utility to convert NIOInputStream
>> input to NIOOutputStream output. But in your case let's figure out if you
>> really need this.
> Actually I don't think I'd need NIOOutputStream at all (I'm not using
> grizzly-server). I'd just need to read NIOInputStream and send the
> first chunk, and at the same time register a ReadListener to send
> further chunks, when data is available (from outbound response) until
> there is no more data.
>
>> Thanks.
>>
>> WBR,
>> Alexey.
>>
>>
>> On 19.06.15 19:18, Daniel Feist wrote:
>>> Yes NIOInputStreamImpl, sorry.
>>>
>>> BTW, any thoughts on the other outbound/AHC pieces of this I mentioned
>>> in my first email?
>>>
>>> Dan
>>>
>>> On Fri, Jun 19, 2015 at 6:14 PM, Oleksiy Stashok
>>> <oleksiy.stashok_at_oracle.com> wrote:
>>>> Hi Dan,
>>>>
>>>> you mean NIOInputStreamImpl implementation is not public, because
>>>> NIOInputStream is public at least in 2.3.x.
>>>>
>>>> WBR,
>>>> Alexey.
>>>>
>>>>
>>>> On 17.06.15 21:51, Daniel Feist wrote:
>>>>> I was thinking of using an extension of InputStream (like
>>>>> NIOInputStream) because I want to be able to support non-blocking,
>>>>> while being backwards compatible with older components that only
>>>>> understand InputStream
>>>>>
>>>>> My filter gets notified on each read yes, but I want an object
>>>>> instance that represents the input body which I can pass on to other
>>>>> components. This object should be compatible with InputStream but
>>>>> also allow for org.glassfish.grizzly.ReadHandler's to be registered.
>>>>> NIOInputStream is actually exactly what I need and I have it
>>>>> integrated it, the primary issue I have with it is it's not public, so
>>>>> currently i'm having to overwrite it's implementation locally. Any
>>>>> reason we can't make this public and potentially move it to
>>>>> http-framework module potentially also?
>>>>>
>>>>> Dan
>>>>>
>>>>>
>>>>> On Wed, Jun 17, 2015 at 8:02 PM, Oleksiy Stashok
>>>>> <oleksiy.stashok_at_oracle.com> wrote:
>>>>>> Hi Dan,
>>>>>>
>>>>>>
>>>>>> On 16.06.15 19:14, Daniel Feist wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> No, not using server API, just transport directly. I didn't look at
>>>>>>> Grizzly buffer because i) Ideally i want it compatible with
>>>>>>> InputStream
>>>>>> Well, InputStream was designed to be blocking, so not sure it's right
>>>>>> approach if you want to be 100% non-blocking.
>>>>>>
>>>>>>> ii) I didn't think Buffer had any mechanism to receive
>>>>>>> notification when there is more data to read, so not sure how you'd
>>>>>>> implement non-blocking read with Buffer.
>>>>>> That's right, but your Filter is getting notified with HttpContent
>>>>>> every
>>>>>> time there is new Buffer to read, so you can feed your output with this
>>>>>> Buffer.
>>>>>> If you want - you can share your code so I could be more specific.
>>>>>>
>>>>>> Thanks.
>>>>>>
>>>>>> WBR,
>>>>>> Alexey.
>>>>>>
>>>>>>
>>>>>>> Dan
>>>>>>>
>>>>>>> On Tue, Jun 16, 2015 at 5:41 PM, Oleksiy Stashok
>>>>>>> <oleksiy.stashok_at_oracle.com> wrote:
>>>>>>>> Hi Daniel,
>>>>>>>>
>>>>>>>> do you use HttpServer API on the server side, or implement it as
>>>>>>>> plain
>>>>>>>> Transport <-> SSLFilter (if needed) <-> HttpServerFilter (codec)
>>>>>>>> FilterChain?
>>>>>>>> I don't think you have to use InputBuffer or OutputSink as data
>>>>>>>> holder
>>>>>>>> to
>>>>>>>> pass from server to client. Why not use Grizzly Buffer?
>>>>>>>>
>>>>>>>> WBR,
>>>>>>>> Alexey.
>>>>>>>>
>>>>>>>>
>>>>>>>> On 12.06.15 11:36, Daniel Feist wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> So i've got a non-blocking proxy running great with inbound
>>>>>>>>> (Grizzly)
>>>>>>>>> -> outbound (ahc ->grizzly) but thats only half the story. Why?
>>>>>>>>> because although no threads are blocking while waiting for a
>>>>>>>>> response
>>>>>>>>> from the target service, I/O is still blocking because what i'm
>>>>>>>>> passing from inbound->outbound is an InputStream. This is maybe not
>>>>>>>>> that important with fast network and small http bodies, but with
>>>>>>>>> slower networks and large bodies I believe it becomes very
>>>>>>>>> important.
>>>>>>>>>
>>>>>>>>> I've had a go at implementing non-blocking read/write but hit a few
>>>>>>>>> challenges and have a few questions.
>>>>>>>>>
>>>>>>>>> - IN:REQUEST: Grizzly has the NIOInputStreamImpl which would do the
>>>>>>>>> job on the inbound side, but I have the following issue. This class
>>>>>>>>> is both in the server module (not much of an issue) and not public
>>>>>>>>> (an
>>>>>>>>> issue), so can't easily be used. This is unideal but easy to work
>>>>>>>>> around, my bigger problems are with outbound.
>>>>>>>>>
>>>>>>>>> - OUT:REQUEST: I've seen the BodyGenerator and PayloadGenerator
>>>>>>>>> abstractions in AHC, but from what I can see there isn't an
>>>>>>>>> implementation that recognises if the the body is a
>>>>>>>>> org.glassfish.grizzly.InputSource in order to perform NIO. Is this
>>>>>>>>> correct? It assume it would simply be necessary implement these
>>>>>>>>> interfaces. That said, there are currently no open extensions
>>>>>>>>> points
>>>>>>>>> from what I can see.
>>>>>>>>>
>>>>>>>>> - OUT:RESPONSE: I was stuck with this one, until after testing I
>>>>>>>>> realised that onBodyPartReceived in AHC AsyncCompletionHandler is
>>>>>>>>> called for every grizzly read() operation and not just for multipart
>>>>>>>>> or chunked messages. I'm unsure if thats the goal of the method or
>>>>>>>>> if
>>>>>>>>> it works with netty, but with grizzly it does. I assume I'd need to
>>>>>>>>> create an instance of NIOInputStreamImpl when i receive the first
>>>>>>>>> buffer within the handle implementation and return it, and then
>>>>>>>>> notify
>>>>>>>>> listeners when with further invocations of onBodyPartReceived, I
>>>>>>>>> haven't quite got my head round it or tried implementing it yet
>>>>>>>>> though.
>>>>>>>>>
>>>>>>>>> - IN:RESPONSE: I haven't looked at this yet other than considering
>>>>>>>>> if
>>>>>>>>> grizzly should consume NIOInputStreamImpl for response or if I'd
>>>>>>>>> need
>>>>>>>>> to convert NIOInputStreamImpl to OutputSink etc. Any thoughts?
>>>>>>>>>
>>>>>>>>> thanks,
>>>>>>>>>
>>>>>>>>> Dan
>>>>>>>>