Mostly IO, non-blocking workload best practice
by Chris Back
I am writing a server that will need to respond to lots of small web
requests. Most of the requests will come with a small POST payload. Based
on the contents of the payload, the server will either a) respond
immediately, or b) forward the request as is to one of a pool of backend
servers, waiting for a response and forwarding the response back to the
client.
It looks like given the existing undertow code, I have good examples of how
to forward requests to the backend. What isn't as clear is how to handle
the getting the POST data. Is there a way of doing that without blocking?
Ideally, my handler flow would be:
1. Non-blocking request handler that makes sure all POST data is in.
2. A non-blocking handler that decisions based on content of POST data to
3a. Immediately return a response to the client (non-blocking).
or
3b. Dispatch to the worker pool to forward request to backend server and
await response.
90% of my requests will go through path 3a, and I'd like that to be as
quick as possible. When the server decides a request should go through 3b,
only then should it go to the blocking worker pool.
Am I viewing this correctly? What are my options? Based on this thread
http://lists.jboss.org/pipermail/undertow-dev/2015-January/001082.html
it seems like an option could be to get the request channel in step 1
above? Its not clear to me how that would work.
Thanks,
Chris
9 years, 2 months
Changing proxy response
by ralf.battenfeld@bluewin.ch
Hi
I am looking for a way to use the LoadBalancingProxyClient that changes the response received from the backend server. I came up with configuring a ResponseCommitListener. Is this the correct way of manipulating the response within the beforeCommit() call?
If yes, how can I change the response with the given HttpServerExchange instance? If not, what would be the best way to achieve this?
Thanks a lot for any help.
Ralf
9 years, 4 months
InSessionMemoryManager synchronized methods
by Eric Peters
Chasing after another problem I found several blocked task threads, best as I can determine:
InMemorySessionmanager$SessionImpl.invalidate() is invoked.
This method is synchronized, and the call blocks inside SesssionListeners.sessionDestroyed() (separate issue there...)
Later, InMemorySessionmanager$SessionImpl.bumpTimeout() is invoked from another thread.
This method is also synchronized, and blocks waiting for invalidate() to complete. As the first thread is indefinitely blocked inside invalidate(), this second thread also remains blocked indefinitely.
In my environment it appears to make an existing problem slightly more severe.
Found in 1.1.0, but it looks like it's in both 1.1.7 and the master branch as well.
Using RHEL, Java 7, Wildfly 8.2
invalidate() Thread trace (excerpt):
* (blocked) - sun.misc.Unsafe.park(boolean, long)
* ...
* org.jboss.seam.contexts.ServletLifecycle.endSession(javax.servlet.http.HttpSession) (line: 187)
* org.jboss.seam.servlet.SeamListener.sessionDestroyed(javax.servlet.http.HttpSessionEvent) (line: 59)
* io.undertow.servlet.core.ApplicationListeners.sessionDestroyed(javax.servlet.http.HttpSession) (line: 264)
* io.undertow.servlet.core.SessionListenerBridge.sessionDestroyed(io.undertow.server.session.Session, io.undertow.server.HttpServerExchange, io.undertow.server.session.SessionListener$SessionDestroyedReason) (line: 67)
* io.undertow.server.session.SessionListeners.sessionDestroyed(io.undertow.server.session.Session, io.undertow.server.HttpServerExchange, io.undertow.server.session.SessionListener$SessionDestroyedReason) (line: 61)
* io.undertow.server.session.InMemorySessionManager$SessionImpl.invalidate(io.undertow.server.HttpServerExchange, io.undertow.server.session.SessionListener$SessionDestroyedReason) (line: 413)
* io.undertow.server.session.InMemorySessionManager$SessionImpl.invalidate(io.undertow.server.HttpServerExchange) (line: 399)
* io.undertow.servlet.spec.HttpSessionImpl.invalidate() (line: 197)
* ...
bumpTimeout() Thread trace:
* io.undertow.server.session.InMemorySessionManager$SessionImpl.bumpTimeout() (line: 271)
* io.undertow.server.session.InMemorySessionManager$SessionImpl.getAttribute(java.lang.String) (line: 355)
* io.undertow.servlet.util.SavedRequest.tryRestoreRequest(io.undertow.server.HttpServerExchange, javax.servlet.http.HttpSession) (line: 124)
* io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 67)
* io.undertow.security.handlers.SecurityInitialHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 76)
* io.undertow.server.handlers.PredicateHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 43)
* org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 61)
* io.undertow.server.handlers.PredicateHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 43)
* io.undertow.server.handlers.PredicateHandler.handleRequest(io.undertow.server.HttpServerExchange) (line: 43)
* io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(io.undertow.server.HttpServerExchange, io.undertow.servlet.handlers.ServletChain, io.undertow.servlet.handlers.ServletRequestContext, javax.servlet.ServletRequest, javax.servlet.ServletResponse) (line: 261)
* io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(io.undertow.server.HttpServerExchange, io.undertow.servlet.handlers.ServletRequestContext, io.undertow.servlet.handlers.ServletChain, javax.servlet.DispatcherType) (line: 247)
* io.undertow.servlet.handlers.ServletInitialHandler.access$000(io.undertow.servlet.handlers.ServletInitialHandler, io.undertow.server.HttpServerExchange, io.undertow.servlet.handlers.ServletRequestContext, io.undertow.servlet.handlers.ServletChain, javax.servlet.DispatcherType)
* io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(io.undertow.server.HttpServerExchange) (line: 166)
* io.undertow.server.Connectors.executeRootHandler(io.undertow.server.HttpHandler, io.undertow.server.HttpServerExchange) (line: 197)
* io.undertow.server.HttpServerExchange$1.run() (line: 759)
* java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (line: 1145)
* java.util.concurrent.ThreadPoolExecutor$Worker.run() (line: 615)
* java.lang.Thread.run() (line: 745)
//EricP
This message has been scanned for malware by Websense. www.websense.com
9 years, 5 months
Lingering session resources in keepalive
by Eric Peters
We're still trying to confirm things on our end, so it's still possible a wrong assumption's been made somewhere, but it looks like session resources are lingering with the http connection after the session has expired.
>From one of the heap dumps, following session data that expired the previous day back to a GC root:
http://imgur.com/Ov8xFy1
That's from a dump where the read-timeout was disabled.
We can set the read-timeout, but I don't know if the behavior of keep-alive will limit the impact of the read timeout. After the reply has been created and sent, do the particulars of the request or reply need to be kept beyond the expiry of the session they were for?
Is there a way to disable keep-alive? In this particular instance it's more important that the resources be freed up timely than it is that the server use keep-alive to give a boost on performance..
//EricP
This message has been scanned for malware by Websense. www.websense.com
9 years, 5 months
No logging?
by Joshua Gitlin
New to Undertow and just trying to put together a few POCs. I'm having some
issues and I'm not seeing any way to turn any sort of verbose logging.
Looks like none fo the default handlers log anything. Any reason there
aren't debug or trace logs with SLF4J or the like?
9 years, 5 months
Question about APR based connector in Undertow
by Andrig T. Miller
I am hearing that some work is being put into an APR based connector for Undertow. I am wondering why we are doing this?
Based on my own testing, and testing the performance team has done with AS 7.x/EAP 6.x/Wildfly, I see no performance reason to do it, and it creates more work for getting product out the door, and maintaining product.
We have found that the APR based connector can exhibit very poor scalability, and consume large amounts of CPU resources when in a network environment that is having problems (TCP resets, dropped and retransmitted packets, etc.).
In this situation, especially where we see these poor network conditions, the APR connector spends a lot of its time managing the connection data structure. That data structure is a ring (doubly linked list with head and tail pointing at each other, which you already know). That ring is sequentially searched for the socket to remove and it locks all access with a mutex before it does this. This causes both a CPU consumption issue, as it sequentially walks the linked list, and a blocking problem. When we first discovered this, I went into the code to see how easy it would be to change it. I don't think this is a simple fix, and since APR is the underpinning of other things, like Apache HTTPD, not a trivial thing to get accepted by the community either. This spurred us to look at the NIO2 based connector, which at the time was unsupported, and it didn't exhibit any of this poor behavior. That's what spurred the effort to move the NIO2 based connector to be fully supported.
In the absence of poor network conditions, the APR connector behaves and performs well, but in the presence of poor network conditions its not good. So, with a viable alternative, which Undertow provides out of the box with its XNIO based architecture, there simple seems no good reason to do with for Undertow.
Thanks.
--
Andrig (Andy) T. Miller
Global Platform Director, JBoss Middleware
Red Hat, Inc.
9 years, 5 months
Websocket: onMessage() called prior to onOpen()
by Guruprasad Nagaraj
Wildfly version: 8.2.0.Final
Undertow version: 1.1.0.Final
Hi,
I am using Undertow web sockets.
A remote client (nopoll c client) attempts to open a websocket session; the session is opened and the client immediately sends a message.
However, at the ServerEndpoint, the onMessage handler is called prior to the onOpen handler.
My server side implementation rejects messages received prior to open and even forces a session close.
The client retries the session, and sometimes it is successful i.e. I do see an open first and then followed by a message by the client.
Is this an known issue?
Sorry, I couldn’t find a way to search the mailing-list archives.
Thanks and Best Regards,
GPN
9 years, 6 months
Undertow doesn't write cookie to response
by John Sipher
Copy/pasted from
https://developer.jboss.org/message/932789?et=watches.email.thread#932789.
Any help would be appreciated...
I'm trying to migrate an application from JBoss 7,.2.0.Final to WildFly
8.2.0.Final, and I find that some cookies are not written to the servlet
response. I've tracked it down to
io.undertow.servlet.spec.HttpServletResponseImpl.addCookie().
1. @Override
2. public void addCookie(final Cookie cookie) {
3. if (insideInclude) {
4. return;
5. }
6. final ServletCookieAdaptor servletCookieAdaptor = new
ServletCookieAdaptor(cookie);
7. if (cookie.getVersion() == 0) {
8.
servletCookieAdaptor.setVersion(servletContext.getDeployment().getDeploymentInfo().getDefaultCookieVersion());
9. }
10. exchange.setResponseCookie(servletCookieAdaptor);
11. }
Apparently the insideCookie flag has been set to true at the point we're
calling HttpServletResponse.addCookie(), so WildFly/Undertow just quietly
throws it away and leaves me scratching my head trying to figure out what
went wrong.
When I search back up the call stack I see that our servlet is including a
JSP page in its response like this
1.
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher(page);
2.
dispatcher.include(state.getRequest(),
state.getResponse());
So, it makes sense that insideInclude is true, since the code that's trying
to set the cookie is being called from inside RequestDispatcher.include(),
but I don't understand why WildFly/Undertow just arbitrarily throws it away.
- See more at:
https://developer.jboss.org/message/932789?et=watches.email.thread#932789
9 years, 6 months
nghttp2 requests to Undertow - "[ERROR] HTTP/2 protocol was not selected. (nghttp2 expects h2)"
by Michael Hixson
I am attempting to make requests to an Undertow+HTTP/2 server with nghttp2.
https://github.com/tatsuhiro-t/nghttp2
The requests fail. I see the same error on the public demo site for
Undertow+HTTP/2, and I don't see any errors when I hit other
HTTP/2-enabled public sites, such as google.com.
The error is "[ERROR] HTTP/2 protocol was not selected. (nghttp2
expects h2)". See the end of this email for full output from the
command line for requests to google.com and http2.undertow.io.
I'm wondering if this is a bug in Undertow. Or perhaps it is a bug in
nghttp2 and I'm on the wrong mailing list. Have any of you tried
this? Any thoughts?
I'm using nghttp2 version 1.1. The Undertow version is whatever the
public demo site is running right now, but I also tried it locally
with the latest from master (1.3.0.Beta1-SNAPSHOT) and got the same
result.
-Michael
----------------------------------------------
$ nghttp -ns https://www.google.com/
***** Statistics *****
Request timing:
responseEnd: the time when last byte of response was received
relative to connectEnd
requestStart: the time just before first byte of request was sent
relative to connectEnd. If '*' is shown, this was
pushed by server.
process: responseEnd - requestStart
code: HTTP status code
size: number of bytes received as response body without
inflation.
URI: request URI
see http://www.w3.org/TR/resource-timing/#processing-model
sorted by 'complete'
id responseEnd requestStart process code size request path
13 +83.40ms +161us 83.24ms 200 19K /
----------------------------------------------
$ nghttp -ns https://http2.undertow.io/
[ERROR] HTTP/2 protocol was not selected. (nghttp2 expects h2)
Some requests were not processed. total=1, processed=0
***** Statistics *****
Request timing:
responseEnd: the time when last byte of response was received
relative to connectEnd
requestStart: the time just before first byte of request was sent
relative to connectEnd. If '*' is shown, this was
pushed by server.
process: responseEnd - requestStart
code: HTTP status code
size: number of bytes received as response body without
inflation.
URI: request URI
see http://www.w3.org/TR/resource-timing/#processing-model
sorted by 'complete'
id responseEnd requestStart process code size request path
9 years, 6 months