-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix session affinity management (stickiness) in wildfly-http-client #108
base: main
Are you sure you want to change the base?
Conversation
…a single service, associating the URL /v<number> path to the service HTTP handler version Signed-off-by: Flavia Rainone <[email protected]>
Signed-off-by: Flavia Rainone <[email protected]>
…classes to enhance readability.
retest please |
sure @rachmatowicz! I am having a look and I'll give you a feedback soon. :-) |
common/src/main/java/org/wildfly/httpclient/common/HttpTargetContext.java
Outdated
Show resolved
Hide resolved
common/src/main/java/org/wildfly/httpclient/common/HttpTargetContext.java
Show resolved
Hide resolved
common/src/main/java/org/wildfly/httpclient/common/HttpTargetContext.java
Show resolved
Hide resolved
common/src/main/java/org/wildfly/httpclient/common/HttpTargetContext.java
Outdated
Show resolved
Hide resolved
@@ -284,6 +284,10 @@ protected SessionID createSession(final EJBReceiverSessionCreationContext receiv | |||
targetContext.awaitSessionId(true, authenticationConfiguration); | |||
CompletableFuture<SessionID> result = new CompletableFuture<>(); | |||
|
|||
// debugging | |||
URI backendURI = targetContext.acquireBackendServer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the best way to add this here? I think that having a blocking invocation at the HttpEJBReceiver will just cause the receiver thread to hold while the other end is responding and this could lead to numerous blocking thread issues.
Ideally, we need a way of having this information available before createSession kicks in, or at least an analysis (maybe you already did that analysis and already know the answer to this question) of why this won't cause thread issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the case, then someone else needs to have a look at this particular issue and do an analysis. It would need to be you or Richard or Paul. The problem is that the code for initializing a transaction and marshaling the transactional state into the invocation (in HttpTargetContext.writeTransaction()) is extremely tightly coupled, and didn't easily allow initializing the transaction (on a backend server chosen by the load balancer) and then using the resulting URI as a target for the invocation.
@@ -20,12 +20,18 @@ | |||
/* | |||
* Versioning enum for HttpHandler implementations. | |||
* | |||
* TODO: due to the way EENamespaceInteroperability.createInteroperabilityHandler(HttpHandler...) works, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I see your point. It is the drawback of introducting the handler version after protocol version is already at number 2. I'm still open to suggestions if you would do it differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about it...
* the original protocol versions JAVAEE_PROTOCOL_VERSION and JAKARTA_PROTOCOL_VERSION need to share | ||
* the same handler instance, so it was not possible to match protocol handler indexes to protocol versions | ||
* in a 1-to-1 manner. In order to avoid a confusing protocol version to handler version mismatch, they share | ||
* the handler installed at index 2. | ||
* TODO: integrate this with the Protocol class in a nice way. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can this be integrated if the idea was to decouple the protocol version from the handlers version?
Maybe we should rename this Version class to HandlerVersion to make it clearer?
And how does this interplay with incremented handler versions in the future, supposing only one type of handler needs to have its version incremented? Say, for example, that only Transaction handlers will need a new request header, or a new parameter, or anything really that is valid only for transaction handlers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have renamed the class. These are good questions. And what if there are Protocol version changes which don't correspond to handler version changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just lost a well-crafted 200 word response to this (with one misplaced click which killed my text :-()
I am looking at this again and here is my idea in a nutshell:
- introduce one Handler class for each of org.wildfly.httpclient.{ejb, transaction, naming} which will contain the handler version for that module, just as the Protocol class holds the protocol version to be used in org.wildfly.httpclient.common. Handler.LATEST serves the same purpose. Use this version when building client requests for ejb, transaction and naming invocations. In other words, the version in the context path is the handler version.
- In the handshake between ClientConnectionHolder, the server-side wrapper functionality of EENamespaceInteroperabilityHandler / JakartaNamespaceHandler and EEInteroperableClientExchange, set things up so that only one combined, context path-independent wrapper is used on the server side, and it is based only on reading the x-wf-version HTTP header to decide which marshaller and unmarshaller factories to attach to requests and replies. In other words, the protocol version is only visible as a HTTP header. When protocol changes occur, the new version and associated changes are confined to those classes: Protocol, ClientConnectionHolder, the new wrapper class, and EEInteroperableClientExchange.
I'm going to have a shot at creating an implementation of this; well, on second thought, it might be better to have a short chat about it first.
@@ -75,6 +82,9 @@ protected void handleInternal(HttpServerExchange exchange) throws Exception { | |||
final String bean = parts[3]; | |||
String invocationId = parts[4]; | |||
boolean cancelIdRunning = Boolean.parseBoolean(parts[5]); | |||
|
|||
// process Cookies and Headers | |||
// TODO: cancellation requires that a Cookie be present |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this incomplete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This is an edge case issue that I planned to return to later.
@Test | ||
@Ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see now. It would be good to have a follow up Jira, unless you plan to tackle this at this Jira only, after this PR is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something I was going to have a look at when I get the basic affinity management working.
@Test | ||
@Ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same here, we either need a follow up Jira or we need to know if there will be a follow up PR for this same Jira (so I can know if I will mark the Jira as resolved after this PR is merged or not).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was something to look at once the basic affinity management is working.
@rachmatowicz I have just reviewed it and I assume that this is the latest version, so this PR is all I'm checking for now. Please let me know if I missed something, and also if there are other points in the code you need feedback for. |
|
||
private static final HttpString STRICT_STICKINESS_HOST = new HttpString("StrictStickinessHost"); | ||
private static final HttpString STRICT_STICKINESS_RESULT = new HttpString("StrictStickinessResult"); | ||
private static final HttpString JSESSIONID_COOKIE_NAME = new HttpString("JSESSIONID"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind, the logic in this class is specific to Apache httpd-based load balancers.
Most other load balancers (e.g. HAProxy) use a distinct cookie for routing. The name of the cookie should be configurable. In this case, there is no need for a "sessionID" cookie, as the SFSB ID is already available via an HTTP header.
This is a draft fix for fixing stickiness in wildfly-http-client: https://issues.redhat.com/browse/WEJBHTTP-81
It is based on wildfly-http-client 2.0.3-SNAPSHOT and Flavia's issue https://issues.redhat.com/browse/WEJBHTTP-106