We ended up implementing hard timeout using CAS; no noticeable drop in
throughput or p99 latency.
I thought I'd share in case others on the list may need it. Here is the
code snippet (using Kotlin).
override fun handleRequest(exchange: HttpServerExchange) {
val timeoutWhenTrue = AtomicBoolean(true)
exchange.getIoThread().executeAfter({
if (timeoutWhenTrue.compareAndSet(true, false)) {
// we're first, so end the exchange
exchange.statusCode = StatusCodes.REQUEST_TIME_OUT
exchange.endExchange()
}
}, requestTimeoutMillis, TimeUnit.MILLISECONDS)
exchange.dispatch(SameThreadExecutor.INSTANCE, Runnable { launch {
//
// request servicing logic
//
if (timeoutWhenTrue.compareAndSet(true, false)) {
response.headers.forEach {
exchange.responseHeaders.add(it.key, it.value }
exchange.statusCode = response.statusCode
response.response?.let {
exchange.responseSender.send(response.response) } ?:
exchange.endExchange() }
}})
}
On Sun, Jul 22, 2018 at 2:59 AM Stan Rosenberg <stan.rosenberg(a)gmail.com>
wrote:
On Sun, Jul 15, 2018 at 7:45 PM, Stuart Douglas
<sdouglas(a)redhat.com>
wrote:
>
>> Are you using the Servlet API or the HttpServerExchange API? The best
>>> way to approach this is a bit different depending on what you are doing.
>>>
>>
>> HttpServerExchange API
>> . Thanks!
>>
>
> This is a bit harder to do in the general case. With Servlet you could
> just create a thread safe wrapper, where the wrapper basically disconnects
> from the underlying request on timeout. The Undertow native API is not
> designed around wrapping though, so it needs cooperation from the
> application to manage this.
>
> If you know the application is only going to be writing data (and not
> setting headers) then you should be able to make this work via a
> ConduitFactory implementation that handles the locking, although if this is
> not the case then you are going to need some kind of external lock.
>
>
Could you please elaborate on the approach using ConduitFactory. Do
you mean using 'exchange.addResponseWrapper' to intercept writes? That
would require locking since write can be invoked from a different thread
concurrently with timeout thread.