nghttpx: Pool h1 backend connection per address

Pool HTTP/1.1 backend connection per address and reuse it only when
the next round robin index refers to this address.  Previously if
there is a pooled connection, there is no round robin selection.
This commit is contained in:
Tatsuhiro Tsujikawa 2019-01-11 23:26:08 +09:00
parent 803d4ba948
commit e9c9838cdc
4 changed files with 38 additions and 54 deletions

View File

@ -658,30 +658,11 @@ void ClientHandler::pool_downstream_connection(
<< " in group " << group; << " in group " << group;
} }
auto &shared_addr = group->shared_addr;
if (shared_addr->affinity.type == SessionAffinity::NONE) {
auto &dconn_pool = group->shared_addr->dconn_pool;
dconn_pool.add_downstream_connection(std::move(dconn));
return;
}
auto addr = dconn->get_addr(); auto addr = dconn->get_addr();
auto &dconn_pool = addr->dconn_pool; auto &dconn_pool = addr->dconn_pool;
dconn_pool->add_downstream_connection(std::move(dconn)); dconn_pool->add_downstream_connection(std::move(dconn));
} }
void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Removing downstream connection DCONN:" << dconn
<< " from pool";
}
auto &dconn_pool =
dconn->get_downstream_addr_group()->shared_addr->dconn_pool;
dconn_pool.remove_downstream_connection(dconn);
}
namespace { namespace {
// Computes 32bits hash for session affinity for IP address |ip|. // Computes 32bits hash for session affinity for IP address |ip|.
uint32_t compute_affinity_from_ip(const StringRef &ip) { uint32_t compute_affinity_from_ip(const StringRef &ip) {
@ -1138,25 +1119,47 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream,
return std::move(dconn); return std::move(dconn);
} }
auto &dconn_pool = shared_addr->dconn_pool; auto end = shared_addr->next;
for (;;) {
auto addr = &shared_addr->addrs[shared_addr->next];
if (addr->proto != Proto::HTTP1) {
if (++shared_addr->next >= shared_addr->addrs.size()) {
shared_addr->next = 0;
}
assert(end != shared_addr->next);
continue;
}
// pool connection must be HTTP/1.1 connection // pool connection must be HTTP/1.1 connection
auto dconn = dconn_pool.pop_downstream_connection(); auto dconn = addr->dconn_pool->pop_downstream_connection();
if (dconn) { if (dconn) {
if (++shared_addr->next >= shared_addr->addrs.size()) {
shared_addr->next = 0;
}
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get() CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get()
<< " from pool"; << " from pool";
} }
} else {
dconn->set_client_handler(this);
return dconn;
}
break;
}
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Downstream connection pool is empty." CLOG(INFO, this) << "Downstream connection pool is empty."
<< " Create new one"; << " Create new one";
} }
dconn = std::make_unique<HttpDownstreamConnection>(group, 0, conn_.loop, auto dconn =
worker_); std::make_unique<HttpDownstreamConnection>(group, 0, conn_.loop, worker_);
}
dconn->set_client_handler(this); dconn->set_client_handler(this);

View File

@ -807,16 +807,6 @@ int HttpDownstreamConnection::end_upload_data() {
namespace { namespace {
void remove_from_pool(HttpDownstreamConnection *dconn) { void remove_from_pool(HttpDownstreamConnection *dconn) {
auto &group = dconn->get_downstream_addr_group();
auto &shared_addr = group->shared_addr;
if (shared_addr->affinity.type == SessionAffinity::NONE) {
auto &dconn_pool =
dconn->get_downstream_addr_group()->shared_addr->dconn_pool;
dconn_pool.remove_downstream_connection(dconn);
return;
}
auto addr = dconn->get_addr(); auto addr = dconn->get_addr();
auto &dconn_pool = addr->dconn_pool; auto &dconn_pool = addr->dconn_pool;
dconn_pool->remove_downstream_connection(dconn); dconn_pool->remove_downstream_connection(dconn);

View File

@ -164,12 +164,6 @@ void Worker::replace_downstream_config(
g->retired = true; g->retired = true;
auto &shared_addr = g->shared_addr; auto &shared_addr = g->shared_addr;
if (shared_addr->affinity.type == SessionAffinity::NONE) {
shared_addr->dconn_pool.remove_all();
continue;
}
for (auto &addr : shared_addr->addrs) { for (auto &addr : shared_addr->addrs) {
addr.dconn_pool->remove_all(); addr.dconn_pool->remove_all();
} }
@ -307,11 +301,9 @@ void Worker::replace_downstream_config(
std::shuffle(std::begin(shared_addr->addrs), std::end(shared_addr->addrs), std::shuffle(std::begin(shared_addr->addrs), std::end(shared_addr->addrs),
randgen_); randgen_);
if (shared_addr->affinity.type != SessionAffinity::NONE) {
for (auto &addr : shared_addr->addrs) { for (auto &addr : shared_addr->addrs) {
addr.dconn_pool = std::make_unique<DownstreamConnectionPool>(); addr.dconn_pool = std::make_unique<DownstreamConnectionPool>();
} }
}
dst->shared_addr = shared_addr; dst->shared_addr = shared_addr;

View File

@ -164,7 +164,6 @@ struct SharedDownstreamAddr {
// TODO Verify that this approach performs better in performance // TODO Verify that this approach performs better in performance
// wise. // wise.
DList<Http2Session> http2_avail_freelist; DList<Http2Session> http2_avail_freelist;
DownstreamConnectionPool dconn_pool;
// Configuration for session affinity // Configuration for session affinity
AffinityConfig affinity; AffinityConfig affinity;
// Next http/1.1 downstream address index in addrs. // Next http/1.1 downstream address index in addrs.