2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/wangle/acceptor/ManagedConnection.h>
22 #include <folly/Memory.h>
23 #include <folly/io/async/AsyncTimeout.h>
24 #include <folly/io/async/HHWheelTimer.h>
25 #include <folly/io/async/DelayedDestruction.h>
26 #include <folly/io/async/EventBase.h>
28 namespace folly { namespace wangle {
31 * A ConnectionManager keeps track of ManagedConnections.
33 class ConnectionManager: public folly::DelayedDestruction,
34 private ManagedConnection::Callback {
38 * Interface for an optional observer that's notified about
39 * various events in a ConnectionManager
43 virtual ~Callback() {}
46 * Invoked when the number of connections managed by the
47 * ConnectionManager changes from nonzero to zero.
49 virtual void onEmpty(const ConnectionManager& cm) = 0;
52 * Invoked when a connection is added to the ConnectionManager.
54 virtual void onConnectionAdded(const ConnectionManager& cm) = 0;
57 * Invoked when a connection is removed from the ConnectionManager.
59 virtual void onConnectionRemoved(const ConnectionManager& cm) = 0;
62 typedef std::unique_ptr<ConnectionManager, Destructor> UniquePtr;
65 * Returns a new instance of ConnectionManager wrapped in a unique_ptr
67 template<typename... Args>
68 static UniquePtr makeUnique(Args&&... args) {
69 return folly::make_unique<ConnectionManager, Destructor>(
70 std::forward<Args>(args)...);
74 * Constructor not to be used by itself.
76 ConnectionManager(folly::EventBase* eventBase,
77 std::chrono::milliseconds timeout,
78 Callback* callback = nullptr);
81 * Add a connection to the set of connections managed by this
84 * @param connection The connection to add.
85 * @param timeout Whether to immediately register this connection
86 * for an idle timeout callback.
88 void addConnection(ManagedConnection* connection,
89 bool timeout = false);
92 * Schedule a timeout callback for a connection.
94 void scheduleTimeout(ManagedConnection* const connection,
95 std::chrono::milliseconds timeout);
98 * Schedule a callback on the wheel timer
100 void scheduleTimeout(folly::HHWheelTimer::Callback* callback,
101 std::chrono::milliseconds timeout);
104 * Remove a connection from this ConnectionManager and, if
105 * applicable, cancel the pending timeout callback that the
106 * ConnectionManager has scheduled for the connection.
108 * @note This method does NOT destroy the connection.
110 void removeConnection(ManagedConnection* connection);
112 /* Begin gracefully shutting down connections in this ConnectionManager.
113 * Notify all connections of pending shutdown, and after idleGrace,
114 * begin closing idle connections.
116 void initiateGracefulShutdown(std::chrono::milliseconds idleGrace);
119 * Destroy all connections Managed by this ConnectionManager, even
120 * the ones that are busy.
122 void dropAllConnections();
124 size_t getNumConnections() const { return conns_.size(); }
126 template <typename F>
127 void iterateConns(F func) {
128 auto it = conns_.begin();
129 while ( it != conns_.end()) {
135 std::chrono::milliseconds getDefaultTimeout() const {
139 void setLoweredIdleTimeout(std::chrono::milliseconds timeout) {
140 CHECK(timeout >= std::chrono::milliseconds(0));
141 CHECK(timeout <= timeout_);
142 idleConnEarlyDropThreshold_ = timeout;
146 * try to drop num idle connections to release system resources. Return the
147 * actual number of dropped idle connections
149 size_t dropIdleConnections(size_t num);
152 * ManagedConnection::Callbacks
154 void onActivated(ManagedConnection& conn);
156 void onDeactivated(ManagedConnection& conn);
159 class CloseIdleConnsCallback :
160 public folly::EventBase::LoopCallback,
161 public folly::AsyncTimeout {
163 explicit CloseIdleConnsCallback(ConnectionManager* manager)
164 : folly::AsyncTimeout(manager->eventBase_),
167 void runLoopCallback() noexcept override {
168 VLOG(3) << "Draining more conns from loop callback";
169 manager_->drainAllConnections();
172 void timeoutExpired() noexcept override {
173 VLOG(3) << "Idle grace expired";
174 manager_->drainAllConnections();
178 ConnectionManager* manager_;
181 enum class ShutdownAction : uint8_t {
183 * Drain part 1: inform remote that you will soon reject new requests.
187 * Drain part 2: start rejecting new requests.
192 ~ConnectionManager() {}
194 ConnectionManager(const ConnectionManager&) = delete;
195 ConnectionManager& operator=(ConnectionManager&) = delete;
198 * Destroy all connections managed by this ConnectionManager that
199 * are currently idle, as determined by a call to each ManagedConnection's
202 void drainAllConnections();
205 * All the managed connections. idleIterator_ seperates them into two parts:
206 * idle and busy ones. [conns_.begin(), idleIterator_) are the busy ones,
207 * while [idleIterator_, conns_.end()) are the idle one. Moreover, the idle
208 * ones are organized in the decreasing idle time order. */
209 folly::CountedIntrusiveList<
210 ManagedConnection,&ManagedConnection::listHook_> conns_;
212 /** Connections that currently are registered for timeouts */
213 folly::HHWheelTimer::UniquePtr connTimeouts_;
215 /** Optional callback to notify of state changes */
218 /** Event base in which we run */
219 folly::EventBase* eventBase_;
221 /** Iterator to the next connection to shed; used by drainAllConnections() */
222 folly::CountedIntrusiveList<
223 ManagedConnection,&ManagedConnection::listHook_>::iterator idleIterator_;
224 CloseIdleConnsCallback idleLoopCallback_;
225 ShutdownAction action_{ShutdownAction::DRAIN1};
228 * the default idle timeout for downstream sessions when no system resource
231 std::chrono::milliseconds timeout_;
234 * The idle connections can be closed earlier that their idle timeout when any
235 * system resource limit is reached. This feature can be considerred as a pre
236 * load shedding stage for the system, and can be easily disabled by setting
237 * idleConnEarlyDropThreshold_ to defaultIdleTimeout_. Also,
238 * idleConnEarlyDropThreshold_ can be used to bottom the idle timeout. That
239 * is, connection manager will not early drop the idle connections whose idle
240 * time is less than idleConnEarlyDropThreshold_.
242 std::chrono::milliseconds idleConnEarlyDropThreshold_;