-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Improve client http connection pools #4975
Conversation
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
.../test-http-client-transport/src/test/java/org/eclipse/jetty/client/ConnectionPoolHelper.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
int pending = AtomicBiInteger.getHi(encoded); | ||
int total = AtomicBiInteger.getLo(encoded); | ||
int pending = pendingConnectionCount.get(); | ||
int total = pool.size() + pending; |
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 still needs to be resolved.
@gregw regarding the The callback now adds the connection to the pool before decrementing the pending connection count. This prevents the Since the above situation is transient, and only happens during warmup or a spike of requests, it wouldn't take long for the pool to eventually reach its max size: I do not think that more than a few attempts would end up not creating the connections and the moer you pile up work, the shorter this situation will last. IMHO it's not worth duplicating the pool size in This is yet another case of "embracing the race" rather than handling it. |
@lorban Still don't like it! |
@gregw I took your idea and ran with it. The |
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.
Much better, but I'd do the total>max test within the addReservation lock.
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
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.
getting closer
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
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 down to just some naming & documentation niggles, plus a thought bubble for another optimisation.
@sbordet has asked some questions that I'd like to see the answers to.. maybe we should have a final hangout on this?, but overall I'm +1
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/ConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
|
||
protected Connection active(Connection connection) | ||
protected Connection activate(int offset) |
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 still have concerns about this - I would like to move the "index" to round-robin only, as others don't need it.
{ | ||
reservationLock.unlock(); | ||
} | ||
} |
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.
Isn't this method very costly now? with the stream filtering and the lock? Can't we use the entry state to "reserve"?
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.
For a certain definition of costly, yes: this method takes a lock and iterates the shared list. But over the Grand Scheme of Things, adding entries to the pool should be a rather uncommon event, I don't think adding new pooled entries every millisecond is a sane behavior after warmup is done. So overall, I don't think it really matters.
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.
As discussed, I think the lock can be made smaller (just rename it from reservationLock
to lock
as it's also used to protect closed
).
Only 138-142 needs to be guarded by the lock.
@Override | ||
public void close() | ||
{ | ||
reservationLock.lock(); |
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.
Why the lock here? I mean that it seems to protect close
but not everywhere, and works on the same variables that are used in other methods but not protected by this lock.
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 only thing that must not happen concurrently is the addition of entries to the shared list, and additions while it is being cleaned up as this could cause:
- overshooting
maxEntries
- overshooting
maxReservations
- creating entries in a closed pool
while concurrently acquiring / releasing / removing entries can be safely handled. So this is what this lock is about.
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.
As discussed, the lock can be reduced to flip closed
, copy the entries, and clear sharedList
.
The iteration can be outside.
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.
Almost there.
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java
Outdated
Show resolved
Hide resolved
@Override | ||
public void close() | ||
{ | ||
reservationLock.lock(); |
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.
As discussed, the lock can be reduced to flip closed
, copy the entries, and clear sharedList
.
The iteration can be outside.
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.
LGTM.
Please remember to use AutoLock
when you merge to 10 in class Pool
which is a new class (and you will have to change the copyright header as well).
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
\o/ So are improved ByteBufferPools next? |
Implemented as part of #4975. Added a test case that proves that the connection is closed when the max usage count is reached. Improved logging. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Fixes #4809 : introduced
setMaxUsageCount(int)
onDuplexConnectionPool
andMultiplexConnectionPool
Fixes #3248 : introduced
preCreateConnections(int)
onAbstractConnectionPool
Modify the HTTP client's connection pooling internal mechanism to stop using queues and removing pooled connections from the pool but rather mark them as they're used and released. This improves performance by 2.5X (worst case) up to 100X (best case).
The pooling algorithm should be generic enough to be reusable for any kind of object pooling (ByteBuffers...)