[undertow-dev] scala, activate, nio, async jdbc, future, threads

Laurent Bedubourg laurent at labe.me
Mon Dec 15 06:40:19 EST 2014


Works like a charm, thanks again.

On Mon Dec 15 2014 at 7:56:49 AM Laurent Bedubourg <laurent at labe.me> wrote:

> Thank you Stuart, I will try this ASAP.
>
> Best regards
> Laurent
>
> On Sun, 14 Dec 2014 23:28 Stuart Douglas <sdouglas at redhat.com> wrote:
>
>> You need to call the HttpServerExchange.dispatch() method, which will
>> prevent the exchange from being ended once the call stack returns.
>>
>> There is however a thread safety issue here, as you can have your
>> callback being called at the same time as the call stack is still
>> returning, which means it is possible to have two threads using the
>> HttpServerExchange, which is not thread safe (in practice this will
>> *probably* work fine, depending on how your code is written).
>>
>> The correct way to deal with this is:
>>
>> HttpServerExchange.dispatch(SameThreadExecutor.INSTANCE, new Runnable() {
>>    public void run() {
>>       //setup callback
>>    }
>> }
>>
>> Basically this does two things, calling dispatch means that the exchange
>> will not be ended when the call stack returns, and dispatching using
>> SameThreadExecutor means that the runnable will be run immediately after
>> the call stack returns in the IO thread (or whatever thread is currently
>> active).
>>
>> If you don't want to use a callback and just want to use await:
>>
>> HttpServerExchange.dispatch(new Runnable() {
>>    public void run() {
>>       //call await()
>>    }
>> }
>>
>> This will dispatch to the worker thread pool, and await() will be called
>> in a worker thread, although if you use this approach you might as well
>> just use plain JDBC, as you loose the benefits of non-blocking IO.
>>
>> Stuart
>>
>> ------------------------------
>>
>> *From: *"Laurent Bedubourg" <laurent at labe.me>
>> *To: *"Jason Greene" <jason.greene at redhat.com>
>> *Cc: *undertow-dev at lists.jboss.org
>> *Sent: *Saturday, 13 December, 2014 6:58:51 PM
>> *Subject: *Re: [undertow-dev] scala, activate, nio, async jdbc, future,
>> threads
>>
>>
>>
>> Thank you very much Jason, it helps me a lot.
>>
>> One last remark regarding "you can save yourself a worker thread and
>> reuse the thread they generate the callback from. At that callback point
>> you can write your response out to the exchange."
>>
>> When I try to do this, calling x.getResponseSender().send(str) un the
>> onSuccess callback of the database future, I got an exception java.lang.IllegalStateException:
>> UT000004: getResponseChannel() has already been called.
>>
>> I imagine that the response has already been somehow cleaned up /
>> modified / terminated by Undertow when the handler exited (I use
>> SessionAttachHandler, date() and routing() in my test).
>>
>> I could not find a way to tell Undertow that I would handle the exchange
>> and end it manually.
>>
>> I am using undertow 1.1.1-final maybe this has been fixed since this
>> version?
>>
>> Thanks again
>>
>> Laurent
>>
>>
>>
>> On Sat Dec 13 2014 at 4:57:33 AM Jason Greene <jason.greene at redhat.com>
>> wrote:
>>
>>> Hello Laurent,
>>>
>>> Your hunch is correct. You never want to block the I/O thread as each
>>> thread is shared between many connections, and a pause prevents them from
>>> being processed. It’s totally reasonable to call dispatch(), which
>>> transfers the exchange to the worker pool where you can wait on a database
>>> reply, and in fact this is a normal pattern. The worker pool is sized to be
>>> pretty large as its expected to host lots of waiters. You can of course
>>> tweak this, or dispatch to your own special pool if you like. The big
>>> advantage to an async database call, even with requiring a worker thread,
>>> is that you can do other work while its running if your pattern fits (e.g.
>>> parallel db calls, iterative computation, etc).
>>>
>>> Alternatively, if the database provides a callback on complete option,
>>> you can save yourself a worker thread and reuse the thread they generate
>>> the callback from. At that callback point you can write your response out
>>> to the exchange.  Just note, that the thread policy of an exchange is that
>>> only one thread at a time can interact with it. If you have a use case
>>> where the a request bounces back and forth (e.g. a very long stream
>>> containing multiple records that must be written to the database as they
>>> com in), then you will need to coordinate locking around that. Such
>>> use-cases though should be weighed against the simplicity of just blocking
>>> in a worker thread.
>>>
>>> To answer a second question you have in a comment from your example,
>>> startBlocking() just enables the use of a plain inputstream/outputstream,
>>> which can only be done once you have dispatched and blocking i/o is now ok.
>>>
>>> Hope this helps,
>>>
>>> -Jason
>>>
>>> > On Dec 12, 2014, at 3:44 PM, Laurent Bedubourg <laurent at labe.me>
>>> wrote:
>>> >
>>> > Ok, I think my mail could be reduced to :
>>> >
>>> > Is it possible possible to transfer the HttpServerExchange
>>> responsibility to another thread ?
>>> >
>>> > Regards
>>> > Laurent
>>> >
>>> >
>>> > On Fri Dec 12 2014 at 7:11:01 PM Laurent Bedubourg <laurent at labe.me>
>>> wrote:
>>> > Hello,
>>> >
>>> > I am evaluating Undertow and trying to fit an async database (with
>>> scala, Activate and https://github.com/mauricio/postgresql-async which
>>> use netty and nio).
>>> >
>>> > The good news is that it more or less works.
>>> >
>>> > My main concern is that the database system create threads using scala
>>> futures and that I am forced to "Await" for the result of my Futures to
>>> send the result to the HttpServerExchange.
>>> >
>>> > I am forced to dispath() the request because Await locks the current
>>> thread and I shouldn't lock the IO thread from my Handler, should I?
>>> >
>>> > It made me wondering : is is really a good idea to use futures + Await
>>> with undertow and more generaly nio?
>>> >
>>> > If the thread pool is limited and I lock threads, even if the database
>>> driver is async and uses nio, am I bitting my own leg?
>>> >
>>> > Thanks for any input you can give me and sorry if it's too scala
>>> related :)
>>> >
>>> > Regards
>>> > Laurent
>>> >
>>> > PS: Here's the handleRequest I am using to test this, any comment or
>>> help welcome too since I am discovering the API.
>>> >
>>> > def handleRequest(x:io.undertow.server.HttpServerExchange){
>>> > if (x.isInIoThread()){
>>> >   x.dispatch(this)
>>> >   return
>>> > }
>>> > // useful or not? no change
>>> > // x.startBlocking()
>>> >
>>> > // Ok, we are in worker thread we can work a little with database
>>> > // val f = asyncTransactionalChain { implicit context =>
>>> > //   for (
>>> > //     a <- asyncTransactional { new AMember("aaa") };
>>> > //     b <- asyncById[AMember](a.id)
>>> > //   ) yield b
>>> > // }
>>> >
>>> > // Simulate database work with just a future
>>> > val f = future {
>>> >   Some(1)
>>> > }(scala.concurrent.ExecutionContext.Implicits.global)
>>> >
>>> > // send string to xchange
>>> > def sendReply(str:String){
>>> >   x.getResponseHeaders().put(io.undertow.util.Headers.CONTENT_TYPE,
>>> "text/plain")
>>> >   x.getResponseSender().send(str)
>>> >   // x.endExchange()
>>> > }
>>> >
>>> > // // this fails
>>> > // f.onSuccess {
>>> > //   case Some(result) => sendReply(result.toString)
>>> > // }(scala.concurrent.ExecutionContext.Implicits.global)
>>> >
>>> > // // this works
>>> > val result = Await.result(f, Duration(1000, MILLISECONDS))
>>> > sendReply(result.toString)
>>> > }
>>> >
>>> > _______________________________________________
>>> > undertow-dev mailing list
>>> > undertow-dev at lists.jboss.org
>>> > https://lists.jboss.org/mailman/listinfo/undertow-dev
>>>
>>> --
>>> Jason T. Greene
>>> WildFly Lead / JBoss EAP Platform Architect
>>> JBoss, a division of Red Hat
>>>
>>>
>>> _______________________________________________
>>> undertow-dev mailing list
>>> undertow-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/undertow-dev
>>
>>
>> _______________________________________________
>> undertow-dev mailing list
>> undertow-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/undertow-dev
>>
>> _______________________________________________
>> undertow-dev mailing list
>> undertow-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/undertow-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/undertow-dev/attachments/20141215/b30cad1a/attachment.html 


More information about the undertow-dev mailing list