-
Notifications
You must be signed in to change notification settings - Fork 704
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
Handle limited open Connections due to keepalive connections #9916
Conversation
a2c3068
to
3ef99c5
Compare
This change set created a linkage error (android), the 'usual' type_info, vtable thing. |
net/Socket.cpp
Outdated
@@ -1298,6 +1385,52 @@ LocalServerSocket::~LocalServerSocket() | |||
# define LOG_CHUNK(X) | |||
#endif | |||
|
|||
bool StreamSocket::checkForcedRemoval(std::chrono::steady_clock::time_point now) noexcept |
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.
might need to move this impl to after
"#endif // !MOBILEAPP" (if mobile needs it) and/or put ifdef MOBILEAPP around it in the header if it doesn't or a !MOBILE stub, something like that anyway
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.
yeah. Great eyes. Thx!
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.
Thanks, @sgothel. There are some really good stuff here!
I understand this is a draft, but it reads like a mix of random fixes and improvements (some of it is good and useful, like adding const
and = default
, make_shared
, etc.), re-inventing methods for doing things already supported, and debugging/tracing support for your understanding (to be removed).
It's very hard to read, as there is no clear theme or purpose.
I left various comments, but I didn't dive too deep in a number of areas because it was unclear why we are either replacing an existing approach, or inventing a new one when we can improve on the existing one (where there are shortcomings).
At a minimum, I'd separate the backtrace improvements from the socket improvements, and likely the misc. improvements from new code/features/tests.
Finally, I'm troubled by vformatString
and the re-working a lot of the socket states and internals with a huge set of new members that change the existing semantics with unclear benefits.
Perhaps there is some context I'm missing. Perhaps this was agreed on and I'm unaware.
Thank you @Ashod for the review.
The draft status was motivated by my intention to discuss the actual semantics and goals, Which brings us to the next point I guess.
When reading commit by commit, I believe everything is well split apart semantically. Indeed, I added a few unrelated single commits into this review. Understanding that we allow
I am not aware of really replacing anything. I merely moved and added functionality.
As described above, a zero side-effect change in its own commit. The Backtrace object in particular is useful for all, as we can produce an instance
I just like printf formatting as it is more performant and flexible (at least to me).
Allow me to continue answering your other remarks below. |
2d51475
to
508ccb0
Compare
I think it'll be easier to manage this if its split up so that the mostly uncontroversial misc cleanups of existing stuff where no change in logic is intended, the make_unique, make_shared, privator ctor -> = delete, constifying, expansion of auto& to real type, emplace_back, etc goes into a separate pr. The backtrace debugging aid looks probably useful to have to me, but can also be its own pr I think (and probably not worth fighting the "CodeQL scanning - action / Analyze" step which apparently can't handle the constexpr use which is blocking ci from passing this pr). And generally trim this pr down to the core change to make it easier to think about it |
Thanks for the responses, @sgothel! We've discussed some offline, so didn't reply here (e.g. printf-style formatting being fast--in fact it's very slow compared to only serialization).
In general, agreed. But I'll echo @caolanm's comment here that breaking up into PRs, that can be decided to merge independent of other parts, is always helpful. I should also point out that this PR is well above a 1000 lines. This is a rare size. Considering that some parts change the interface of a large hierarchy (the sockets), which is a fundamental core part of the whole project and very delicate (can easily break things catastrophically), it requires reading and studying far more code (i.e. the context and consequences) to review properly. An isolated and low-risk change of a few 100 lines is fine. A complex few 100 line change (such as in the sockets) is challenging and time consuming. Sometimes we have no choice because we can't break it up. But a 1000 lines that can be easily broken up is hardly necessary. Finally, even though we can review individual commits, it's preferable to have a single theme to a PR. Helps the reviewer. In some cases a few misc. changes can go together (comment fixes, cosmetics, formatting, logging, etc.). But mixing functional changes with non-functional changes dilutes the process and can reduce the quality of the review. More so with high-risk changes (i.e. socket code) mixed with debugging code (i.e. backtracing). Regardless, you have a lot of great improvements here, and I don't want to undermine the importance of your contribution! |
508ccb0
to
cb801db
Compare
Thank you both for your review and kind words. I have split up single commits into 4 branches, i.e. this pull-request branch and
For this feature work, I need to complete the unit test incl. the timeout configuration. |
cb801db
to
6fc374e
Compare
6fc374e
to
31c1b94
Compare
@sgothel, there were multiple suggestions to split this large PR up to reduce its size. That was when it had 18 commits and was "only" a 1000 lines. Now it's past 1500 lines and is 1 commit! I'm sensing this isn't going in the direction of the feedback. What's the plan, please? |
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 said needs to be split up; lets try to get the less controversial pieces in and merged as separate pull requests - to slim this down =) Can you work on that Sven ?
will do the split later then (tomorrow) + finishing the tests |
As I wrote, I will split out the config and TimeAverage (~400 lines or so) and put the remainder at the bottom -> 3 commits within this pull request. Perhaps more, w/ a fresh look. But splitting this up in multiple pull request (PR) makes would probably makes no sense, as these pieces are required and each PR must be tested. IMHO. |
Preparation for cool#9833, to be used to provide a time-based ping response time average. TimeAverage allows us to calculate the time based average of a value while adding new time-point/value tuples at arbitrary time-points. The result is stable against small fluctuations and shall provide a reasonable actionable criteria. Signed-off-by: Sven Göthel <[email protected]> Change-Id: I7e1a9329e0848c40a210f6250e29e26950da6fbc
…imeout) Preparation for cool#9833. Using runtime mutable defaults for network properties allows us to test the socket limitation code as well as to fine-tune certain properties for clients. Costs are removal of constexpr properties, using a static local (singleton) instance, cached where used - hence rendering the code less optimized and more pessimistic. However, the singleton instance is fetched at object creation w/o cache hit using a static-local, networking timing outweights memory reads and no hot-spot performance heavy loop is affected. Hence rendering the feature testable at runtime shall outweight the lesser costs. - All network limits and timeouts are configurable within our unit tests only - see net::Defaults in NetUtil.hpp Signed-off-by: Sven Göthel <[email protected]> Signed-off-by: Caolán McNamara <[email protected]> Change-Id: I7e1a9329e0848c40a210f6250e29e26950da6fbc
…incl. creation- and lastSeenTime Socket Restructuring: - Unify stats(bytes + throughput) - Persistent creationTime (immutable) and lastSeenTime (mutable) Signed-off-by: Caolán McNamara <[email protected]> Signed-off-by: Sven Göthel <[email protected]> Change-Id: If9e3b28cfd4c6fdb73b978b80ef2063c63def6d1
moved `StreamSocket::_lastSeenHTTPHeader` to `std::chrono::steady_clock::time_point &lastHTTPHeader` where it is being required - reduces general footprint. Signed-off-by: Sven Göthel <[email protected]> Signed-off-by: Caolán McNamara <[email protected]> Change-Id: I5148fa7ee2aa5ce88ef8bf31c2e036921d01277c
- ProtocolHandlerInterface::checkTimeout(..) is now called via StreamSocket::checkRemoval() to ensure tests even w/o input data (was: handlePoll()) - ProtocolHandlerInterface::checkTimeout(..) - Add bool return value: true -> shutdown connection, caller shall stop processing - Implemented for http::Session - Timeout (30s) net::Defaults::HTTPTimeout with missing response - Implemented for WebSocketHandler - Timeout (2s = net::Defaults::WSPingTimeout) after missing WS native frame ping/pong (server only) - StreamSocket::checkRemoval(..) - called directly from SocketPoll::poll() - only for IPv4/v6 network connections - similar to ProtocolHandlerInterface::checkTimeout(..) - calls ProtocolHandlerInterface::checkTimeout(..) - added further criteria (throughput, ..) - Timeout (64s = net::Defaults::SocketPollTimeout) if (now - lastSeen) > timeout - Timeout (net::Defaults::MinBytesPerSec) if Throughput < MinBytesPerSec (disabled by default) - TODO: Add maximal IPv4/IPv6 socket-count criteria, drop oldest. - age via Socket::creationTime is currently not used as requested - SocketPoll::poll() - Additionally erases if !socket->isOpen() || socket->checkRemoval() Signed-off-by: Sven Göthel <[email protected]> Signed-off-by: Caolán McNamara <[email protected]> Change-Id: I7e1a9329e0848c40a210f6250e29e26950da6fbc
Adding connection limit where registered via SocketPoll::setLimiter(), i.e. DocumentBrokerPoll and WebServerPoll only. SocketPoll::poll() will drop _new_ overhead connections exceeding MaxConnections. This has been discussed, in favor of dropping the oldest connections. Aligned net::Defaults::MaxConnections w/ pre-existing MAX_CONNECTIONS. SocketPoll::setLimiter(): - Increments given non-zero connectionLimit by one for WS upgrade socket. Signed-off-by: Sven Göthel <[email protected]> Change-Id: I7e1a9329e0848c40a210f6250e29e26950da6fbc
test/UnitTimeoutBase.hpp - Base for UnitTimeout* tests test/UnitTimeoutNone.cpp - Test without limitation, no disconnection test/UnitTimeoutConnections.cpp - Test disconnection with limited max-connections (5) via net::Defaults test/UnitTimeoutWSPing.cpp - Test disconnection with limited WSPingTimout (20us) using WSPingPeriod (10ms) via net::Defaults test/UnitTimeoutSocket.cpp - Test disconnection with limited MinBytesPerSec (100kBps) via net::Defaults test/WebSocketSession's WebSocketSession::poll() added a isConnected() check allowing to abort. Signed-off-by: Sven Göthel <[email protected]> Change-Id: I7e1a9329e0848c40a210f6250e29e26950da6fbc
Signed-off-by: Sven Göthel <[email protected]> Signed-off-by: Caolán McNamara <[email protected]> Change-Id: I9f7a6fbbf93381de72471ea878582f8e5db88962
1f60a19
to
607a062
Compare
StreamSocket::checkRemoval does something on (cNow || cIDLE || cMinThroughput || cTermination ) where: cTermination is SigUtil::getTerminationFlag() which looks straightforward cNow is cNow = now < getCreationTime() which is presumably never in practice cMinThroughput depends on _minBytesPerSec getting set to non-zero which is not enabled by default (test/UnitTimeoutSocket.cpp uses it) so doesn't (currently) affect normal usage cIDLE is durLast > _pollTimeout; where _pollTimeout is 64secs (preexisting value as DefaultPollTimeoutMicroS) |
Regression injected with commit 0579ee8 of PR #9916 Original behavior was to do nothing in Socket::shutdown(), while the commit in question did setClosed() leading to an eventual socket close within SocketPoll::poll(). The latter causes an error within system ::ppoll(). Signed-off-by: Sven Göthel <[email protected]> Change-Id: I57d46e0428905137e05d34dad450fea1d6a0f127
Regression injected with commit 0579ee8 of PR #9916 Original behavior was to do nothing in Socket::shutdown(), while the commit in question did setClosed() leading to an eventual socket close within SocketPoll::poll(). The latter causes an error within system ::ppoll(). Signed-off-by: Sven Göthel <[email protected]> Change-Id: I57d46e0428905137e05d34dad450fea1d6a0f127
Regression injected with commit 0579ee8 of PR #9916 Original behavior was to do nothing in Socket::shutdown(), while the commit in question did setClosed() leading to an eventual socket close within SocketPoll::poll(). The latter causes an error within system ::ppoll(). Signed-off-by: Sven Göthel <[email protected]> Change-Id: I57d46e0428905137e05d34dad450fea1d6a0f127
…` minimum throughput PR #9916 added `MinBytesPerSec` minimum throughput criteria for checkRemoval to limit connections, i.e. cleaning up unresponsiveness or lagging sockets. Due to its unreliable nature per request, the criteria has been disabled per default but remained in the code test w/ UT UnitTimeoutSocket. Turns out that even the UT may fail on certain test setups. We decided to remove this criteria altogether, as it will nor be used. Signed-off-by: Sven Göthel <[email protected]> Change-Id: I9212cdf8b87c1c7b0df5761db956cbaa4fd44f58
…` minimum throughput PR #9916 added `MinBytesPerSec` minimum throughput criteria for checkRemoval to limit connections, i.e. cleaning up unresponsiveness or lagging sockets. Due to its unreliable nature per request, the criteria has been disabled per default but remained in the code test w/ UT UnitTimeoutSocket. Turns out that even the UT may fail on certain test setups. We decided to remove this criteria altogether, as it will nor be used. Signed-off-by: Sven Göthel <[email protected]> Change-Id: I9212cdf8b87c1c7b0df5761db956cbaa4fd44f58
Regression injected with commit 0579ee81c709865ea420c2d70dcc443bdf69de1a of PR CollaboraOnline/online#9916 Original behavior was to do nothing in Socket::shutdown(), while the commit in question did setClosed() leading to an eventual socket close within SocketPoll::poll(). The latter causes an error within system ::ppoll(). Signed-off-by: Sven Göthel <[email protected]> Change-Id: I57d46e0428905137e05d34dad450fea1d6a0f127
Summary
ProtocolHandlerInterface::checkTimeout(..)
is now called via StreamSocket::checkRemoval()
to ensure tests even w/o input data (was: handlePoll())
ProtocolHandlerInterface::checkTimeout(..)
after missing WS native frame ping/pong (server only)
StreamSocket -> Socket (properties moved)
Socket (added properties)
if (now - lastSeen) > timeout
if Throughput < MinBytesPerSec (disabled by default)
SocketPoll::poll()
Changes to original PR
Further:
and before moved _lastSeenHTTPHeader
git rebase -i --exec "make -j 20"
for all commitsUnit tests: +7 files, 879 insertions(+), remaining changed lines +800, -222
Checklist
make prettier-write
and formatted the code.make check
make run
and manually verified that everything looks okay