users@grizzly.java.net

Re: Non-Blocking Read/Write in Proxy

From: Daniel Feist <dfeist_at_gmail.com>
Date: Mon, 29 Jun 2015 14:32:51 +0100

Hi,

I'm no sure how quickly I'll get to this, but I'll let you know how it
goes, once I get chance to work on it.

thanks!

On Wed, Jun 24, 2015 at 2:09 PM, Oleksiy Stashok
<oleksiy.stashok_at_oracle.com> wrote:
> 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
>>>>>>>>>>>
>>>>>>>>>>>
>