-
Notifications
You must be signed in to change notification settings - Fork 984
HTTPCLIENT-2398 - Cap async execution queue to break recursive re-entry #728
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
base: master
Are you sure you want to change the base?
Conversation
|
@arturobernalg Could you please rebase this change-set? |
35f4730 to
d33aa28
Compare
...lient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
Outdated
Show resolved
Hide resolved
...lient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
Outdated
Show resolved
Hide resolved
...lient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
Outdated
Show resolved
Hide resolved
ok2c
left a comment
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.
@arturobernalg This is a good start. Please also do not forget about InternalH2AsyncExecRuntime.
...lient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
Outdated
Show resolved
Hide resolved
ce23427 to
a6a1eec
Compare
0996102 to
9b9e1d4
Compare
|
@arturobernalg Looks good. Can we add the same functionality to |
d705c34 to
3bab080
Compare
@ok2c please do another pass |
| final RequestConfig requestConfig = context.getRequestConfigOrDefault(); | ||
| @SuppressWarnings("deprecation") | ||
| final Timeout connectTimeout = requestConfig.getConnectTimeout(); | ||
| @SuppressWarnings("deprecation") final Timeout connectTimeout = requestConfig.getConnectTimeout(); |
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.
@arturobernalg There is again plenty of white space / formatting noise. Please try to avoid it.
| } | ||
| } | ||
|
|
||
| private AsyncClientExchangeHandler guard(final AsyncClientExchangeHandler handler) { |
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.
@arturobernalg I am not super crazy about code re-use at all cost but in this case there is just too much duplicate code. Please consider extracting into a separate proxy class similar to RequestEntityProxy / ResponseEntityProxy
b7e1ad4 to
111d293
Compare
|
|
||
| } | ||
|
|
||
| private static final ConcurrentMap<AsyncClientConnectionManager, AtomicInteger> QUEUE_COUNTERS = |
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.
@arturobernalg This is bad. We need to find a way to maintain the counter without using a static hash map. The limit should ideally be per connection. If this is too difficult, then, per client instance.
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.
@ok2c please do another pass
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.
@arturobernalg Do not see how this is any better. The static map is still there and what you have is essentially a major resource leak right there.
6291a62 to
707f4cb
Compare
|
|
||
| } | ||
|
|
||
| private static final ConcurrentMap<AsyncClientConnectionManager, AtomicInteger> QUEUE_COUNTERS = |
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.
@arturobernalg Do not see how this is any better. The static map is still there and what you have is essentially a major resource leak right there.
07a3647 to
1272d81
Compare
|
@ok2c got it. No more static var. |
ad57ea3 to
319e3d8
Compare
|
@arturobernalg This is better. Please mark new setters in the builder classes as experimental. Okay, this is what we have now Users could now limit the number of concurrent active requests on a per client basis. How useful is that, though? Say, one sets max concurrent request number to 1000, then opens 100 active connections and equally distributes requests over those connections. 10 concurrent requests per connection is very little. However, having just one connection and trying to execute 1000 requests concurrently over it would likely be wrong. What would be more useful is to cap the total number of requests on a per connection basis. What could also be useful is enqueuing requests instead of failing them and executing them as soon as the number of concurrent requests drops below the maximum. Moreover, the same queuing mechanism could be used to re-queue and retry requests that did not get executed due to the opposite endpoint closing the connection. This change-set is a start in the right direction. Let's keep it though clearly marked as experimental for now. |
319e3d8 to
2ced361
Compare
…ry. Add configurable maxQueuedRequests (default unlimited). Release slot on fail/cancel/close to avoid leaks
ce8cc75 to
ea8d09f
Compare
@ok2c Marked the new builder setters as @experimental. Agreed on the limitations of a per-client cap; I’ll keep this change-set scoped to fail-fast limiting for now. I’ll follow up with separate PRs for (1) per-connection caps and (2) optional bounded queuing / re-queue of not-yet-started requests. |
@arturobernalg Please note this will likely have to be done in core. |
@ok2c Ill take a look the option to move it to the core |
Implements Option 1 from the discussion: add a configurable cap on the
asyncexecution pipeline to prevent the recursive callback loop that led toStackOverflowError.