Problem
If jvmRoute contains symbol =, the session stickiness breaks. The following example operates with a jvmRoute that contain dots and other symbols, but the issue is reproducible wit as simple jvmRoute as: worker=1. The symbol should be properly parsed and used or rejected as suspicious, alongside with < and such. I incline to the former, i.e. parsing it properly.
Symptoms
- session ID remains the same
- jvmRoute appended to the session ID remains the same – which is especially misleading
- the servlet is actually executed on random nodes, see undermentioned example
Example
Client
date;curl 192.168.122.172:8080/clusterbench/requestinfo -b cookie.txt -c cookie.txt
Test
Follows sequence of client and server log outputs, note header's Cookie=JSESSIONID=... and servlet's JVM route:
Client event |
---|
Mon Apr 4 05:29:56 EDT 2016 Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172} JVM route: .worker.-2=... Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca Session isNew: false Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d |
Server event |
05:29:56,395 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:56,395 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:56,396 DEBUG [io.undertow.request] (default I/O-4) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@655c8ba8 to prevent listener runaway 05:29:56,403 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Received response io.undertow.client.ClientResponse@1b177dc5 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} |
Client event |
Mon Apr 4 05:29:56 EDT 2016 Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172} JVM route: .worker.-2=... Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca Session isNew: false Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d |
Server event |
05:29:56,859 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:56,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:56,860 DEBUG [io.undertow.request] (default I/O-3) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@18859d68 to prevent listener runaway 05:29:56,867 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Received response io.undertow.client.ClientResponse@366ef93b for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:56,891 DEBUG [io.undertow] (default I/O-4) UT005040: Gonna send payload: HTTP/1.0 200 OK Date: Mon, 4 Apr 2016 05:29:56 -0400 Sequence: 217 Digest: b28e7f72ae2c17ba6971bf5eeac50d45 Server: fbacdea8-4950-4c32-a064-91ff48db17e1 X-Manager-Address: rhel7GAx86-64:8080 X-Manager-Url: / X-Manager-Protocol: httpd X-Manager-Host: rhel7GAx86-64 |
Client event |
Mon Apr 4 05:29:57 EDT 2016 Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172} JVM route: ......worker.-1=... Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca Session isNew: false Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@66524317 |
Server event |
05:29:57,349 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:57,349 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:57,349 DEBUG [io.undertow.request] (default I/O-2) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@7839d343 to prevent listener runaway 05:29:57,353 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Received response io.undertow.client.ClientResponse@73974106 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} |
Client event |
Mon Apr 4 05:29:57 EDT 2016 Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172} JVM route: .worker.-2=... Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca Session isNew: false Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d |
Server event |
05:29:57,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:57,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} 05:29:57,860 DEBUG [io.undertow.request] (default I/O-1) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@16c1c959 to prevent listener runaway 05:29:57,873 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Received response io.undertow.client.ClientResponse@327d939 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}} |
Expected result
Both workers are available and sticky sessions are enabled – we expect to keep having responses from single worker with the same session.
WDYT?
- is cloned by
-
JBEAP-4072 mod_cluster proxy: If jvmRoute contains symbol = session stickiness is broken
- Closed