-
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
Total connections created exceeding expected count for fix amount of requests #5068
Comments
This has been addressed and fixed in #4904 which is available in Jetty 9.4.30. |
Hi, Tried with the latest version (9.4.30.v20200611) also, still the same issue. As we are trying to create a round-robin connection pool, with configurable stream IDs. The streams of a connection gets exhausted on reaching the value of max streams per connection. So we have extended the class AbstractConnectionPool (also implements Multiplexable) and created our connection pool by overriding some of the methods. The remove() and release() method, implementations can also be found in the file shared earlier. Our implemention of activate() method with stream ID exhaustion: protected Connection activate()
{
System.out.println("************ Activate **************");
Connection connection = null;
lock();
try
{
int offset = 0;
int capacity = getMaxConnectionCount();
while (offset < capacity)
{
int idx = index + offset;
if (idx >= capacity)
idx -= capacity;
Entry entry = entries.get(idx);
if (entry.connection == null)
break;
if (entry.active < getMaxMultiplex())
{
++entry.active;
++entry.used;
connection = entry.connection;
System.out.println("Request Count --> " + requestCount.incrementAndGet());
if (entry.used == maxStreamsPerConnection)
{
Entry tmpEntry = new Entry();
tmpEntry.active = entry.active;
tmpEntry.used = entry.used;
expiredConnections.put(connection, tmpEntry);
entry.reset();
}
index += offset + 1;
if (index >= capacity)
index -= capacity;
break;
}
++offset;
}
}
finally
{
unlock();
}
System.out.println("************ end Activate **************" + connection);
return connection == null ? null : active(connection);
} Example(as the scenario run in log): Please find attched logs for the same. Please suggest, is this an issue? or are we missing something? |
hi, As part of our ongoing investigation, we had below observation: Whenever we hit a request, the request lands on the HttpDestination class. In this class a private method process() is invoked from the send() method, which gets the connection pool and on that connection process that request. With the existing implementation, we are getting the connections used count getting incremented more number of times than the expected count(Total requests hit). But if we change the existing implementation of the send() method (make it synchronized), we are getting the expected result. Existing code:
Modified Code:
Though we have an impact on tps with this change, but from functionality point it is giving desired result. |
If you have Using a lock per destination is not something we will do - it will kill the performance. In summary, I don't understand what you want. If this is still the behavior you want, it's not currently implemented and you have to write your own connection pool. The key thing to understand is that both the sending thread and the receiving thread compete to send queued requests. The only exception is |
Hello sbordet, Thanks for your response. Basically our requirement is to configure maximum streams per connection. In the current implementation, each connection serve Integer.Max_Value streams. we need to configure these stream id's per connection, so when each connection completed configured number of stream, it will set for Idle Timeout and new connection would be created to maintain maximum number of connection. We have created our own Round Robin connection pool where our connection pool maintain the maximum number of stream per connection but unfortunately since multiple thread are calling HttpDestination.send method, so sometime connection is returned from acquired method of connection pool but not used for sending the request. This means, if we send 25 request in connection there is possibility of acquired method will be called more than 25 times. We understand that in case multiplexing, request thread and response thread should quarantine the connection until all request are completed. We have done similar changes as we are making connection idle for some time before closing the connection so that are request are completed. We only need to configure maximum stream per connection and want to close connection if maximum stream is reached and create a new connection. We already provided our connection pool implementation above. Kindly suggest the way forward are we missing anything or there is other way to implement this functionality.?? |
I think this is the same as #4809 then. Does your implementation work after the changes? |
Hello sbordet, We are able to close the connection, when the max stream per connection are consumed, by making the connection idle timeout, and not getting the exception AsynchronousCloseException. Kindly suggest the way forward are we missing anything or there is other way to implement this functionality.?? |
We fixed #4904 in 9.4.31 (sorry, above I said 9.4.30, but it's in 9.4.31). |
The JARs for version 9.4.31, are not yet available in maven repo. Where can we get the latest JARs? |
You can build Jetty yourself (easy, see https://www.eclipse.org/jetty/documentation/current/contributing-source-build.html and build skipping the tests: Or you can reference this repository in your POM: It currently contains version 9.4.31 that has been staged, we are testing it, and we will release it in a day or so. Or you can wait a day or so for 9.4.31 to appear in Maven Central. |
Hello sbordet, We tried with version 9.4.31 also, but still having the issue. In the latest code also, the acquire() method is called with the boolean create variable. In this case the connection will only be created when the connection is null and create is true.
But the acquire() method is still called more number of times, which in turn calls activate() method.
So in our scenario, there might be some threads which have got the connection (incremented the streams used count), but didn't serve any requests, and this would in turn close the connection before utilizing all streams (equal to max streams per connection). There might be a possibility that the active count of connection might not reach to 0 due to this same behavior while releasing the connection and hence it may not be marked idle. We are setting the max Connection per destination and max Streams per connection accordingly. |
The design of This is done for necessity (if the sender thread stops sending, queued requests need to be sent by the receiver thread) as well as performance. We are not going to change this. A Commercial load balancers are not perfect either, they may send requests to 2 servers in a non perfect alternance. You have not explained why you really need to be that strict on your logic. Having said that, you have found the solution of synchronizing |
Closing as resolved. |
Jetty version
9.4.24.v20191120
Java version
1.8 b251
OS type/version
linux (RHEL 7.7)
Description
Why the number of connections to the server are exceeding the expected number of connections?
We are trying to create a round-robin connection pool, with max-streams support which is configurable. When the max-streams of the connection are exhausted, the connection is reset, and a new connection is created in its place.
But the behavior is inconsistent, and newer connections are created, before the max streams of these connections are exhausted.
For example:
Max Connections: 3
Max Streams per connection: 10
We are send 30 requests, we need these 3 connections to serve all the requests(3 * 10 = 30) in round robin manner, and no new connection should be created.
Upon receiving the 31st request, and new connection should be created, as the older connection's streams have been exhausted. Same for 32nd and 33rd request.
But the behavior is inconsistent, and newer connections are created, even while serving these 30 requests.
Please find the file attached for the same(zipped):
RoundRobinConnectionPoolWithStreamId.zip
The text was updated successfully, but these errors were encountered: