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,26 +1119,48 @@ 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];
// pool connection must be HTTP/1.1 connection if (addr->proto != Proto::HTTP1) {
auto dconn = dconn_pool.pop_downstream_connection(); if (++shared_addr->next >= shared_addr->addrs.size()) {
shared_addr->next = 0;
}
if (dconn) { assert(end != shared_addr->next);
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get() continue;
<< " from pool";
}
} else {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Downstream connection pool is empty."
<< " Create new one";
} }
dconn = std::make_unique<HttpDownstreamConnection>(group, 0, conn_.loop, // pool connection must be HTTP/1.1 connection
worker_); auto dconn = addr->dconn_pool->pop_downstream_connection();
if (dconn) {
if (++shared_addr->next >= shared_addr->addrs.size()) {
shared_addr->next = 0;
}
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get()
<< " from pool";
}
dconn->set_client_handler(this);
return dconn;
}
break;
} }
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Downstream connection pool is empty."
<< " Create new one";
}
auto dconn =
std::make_unique<HttpDownstreamConnection>(group, 0, conn_.loop, worker_);
dconn->set_client_handler(this); dconn->set_client_handler(this);
return dconn; return dconn;

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,10 +301,8 @@ 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.