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
-