users@grizzly.java.net

Re: Non-Blocking Read/Write in Proxy

From: Oleksiy Stashok <oleksiy.stashok_at_oracle.com>
Date: Wed, 24 Jun 2015 15:09:48 +0200

Hi,


On 23.06.15 15:57, Daniel Feist wrote:
> 1) Does it makes sense to make NIOInputStreamImpl public or provide a
> factory for creating instance of NIOInputStream in Grizzly itself, i
> can create my own implementation but it's fairly tedious and if i'm
> going to wrap org.glassfish.grizzly.http.io.InputBuffer anyway..
Factory or some wrapper approach looks fine to me, can you pls. suggest
the patch, that covers changes for NIOInputStream/NIOReader and
NIOOutputStream/NIOWriter?

> 2) When you say "BinaryNIOInputSource (or NIOInputStream) could be
> used to feed the client request body." you are agreeing a new custom
> Feeder is required right? That isn't currently anything that does
> this.
No, there is nothing ready, what you probably need is to implement
NonBlockingFeeder that will pull data out of NIOInputStream in
non-blocking mode.

Thanks.

WBR,
Alexey.

>
> thanks!!
>
> On Tue, Jun 23, 2015 at 2:46 PM, Oleksiy Stashok
> <oleksiy.stashok_at_oracle.com> wrote:
>> 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
>>>>>>>>>>