nghttpx: Fix bugs and crash when affinity is enabled
This commit is contained in:
parent
143d0b69b7
commit
f9897f8ccd
|
@ -302,4 +302,6 @@ APIDownstreamConnection::get_downstream_addr_group() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DownstreamAddr *APIDownstreamConnection::get_addr() const { return nullptr; }
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
virtual bool poolable() const;
|
virtual bool poolable() const;
|
||||||
|
|
||||||
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
||||||
|
virtual DownstreamAddr *get_addr() const;
|
||||||
|
|
||||||
int send_reply(unsigned int http_status, int api_status);
|
int send_reply(unsigned int http_status, int api_status);
|
||||||
|
|
||||||
|
|
|
@ -669,8 +669,18 @@ void ClientHandler::pool_downstream_connection(
|
||||||
<< " in group " << group;
|
<< " in group " << group;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &dconn_pool = group->shared_addr->dconn_pool;
|
auto &shared_addr = group->shared_addr;
|
||||||
dconn_pool.add_downstream_connection(std::move(dconn));
|
|
||||||
|
if (shared_addr->affinity == AFFINITY_NONE) {
|
||||||
|
auto &dconn_pool = group->shared_addr->dconn_pool;
|
||||||
|
dconn_pool.add_downstream_connection(std::move(dconn));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto addr = dconn->get_addr();
|
||||||
|
auto &dconn_pool = addr->dconn_pool;
|
||||||
|
dconn_pool->add_downstream_connection(std::move(dconn));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
|
void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
|
||||||
|
@ -715,7 +725,6 @@ Http2Session *ClientHandler::select_http2_session_with_affinity(
|
||||||
|
|
||||||
if (addr->http2_extra_freelist.size()) {
|
if (addr->http2_extra_freelist.size()) {
|
||||||
auto session = addr->http2_extra_freelist.head;
|
auto session = addr->http2_extra_freelist.head;
|
||||||
session->remove_from_freelist();
|
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "Use Http2Session " << session
|
CLOG(INFO, this) << "Use Http2Session " << session
|
||||||
|
@ -727,8 +736,8 @@ Http2Session *ClientHandler::select_http2_session_with_affinity(
|
||||||
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
||||||
<< session << ").";
|
<< session << ").";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
session->add_to_avail_freelist();
|
session->remove_from_freelist();
|
||||||
}
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
@ -740,7 +749,7 @@ Http2Session *ClientHandler::select_http2_session_with_affinity(
|
||||||
CLOG(INFO, this) << "Create new Http2Session " << session;
|
CLOG(INFO, this) << "Create new Http2Session " << session;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->add_to_avail_freelist();
|
session->add_to_extra_freelist();
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ class ClientHandler;
|
||||||
class Upstream;
|
class Upstream;
|
||||||
class Downstream;
|
class Downstream;
|
||||||
struct DownstreamAddrGroup;
|
struct DownstreamAddrGroup;
|
||||||
|
struct DownstreamAddr;
|
||||||
|
|
||||||
class DownstreamConnection {
|
class DownstreamConnection {
|
||||||
public:
|
public:
|
||||||
|
@ -61,6 +62,7 @@ public:
|
||||||
virtual bool poolable() const = 0;
|
virtual bool poolable() const = 0;
|
||||||
|
|
||||||
virtual DownstreamAddrGroup *get_downstream_addr_group() const = 0;
|
virtual DownstreamAddrGroup *get_downstream_addr_group() const = 0;
|
||||||
|
virtual DownstreamAddr *get_addr() const = 0;
|
||||||
|
|
||||||
void set_client_handler(ClientHandler *client_handler);
|
void set_client_handler(ClientHandler *client_handler);
|
||||||
ClientHandler *get_client_handler();
|
ClientHandler *get_client_handler();
|
||||||
|
|
|
@ -543,4 +543,6 @@ Http2DownstreamConnection::get_downstream_addr_group() const {
|
||||||
return http2session_->get_downstream_addr_group();
|
return http2session_->get_downstream_addr_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DownstreamAddr *Http2DownstreamConnection::get_addr() const { return nullptr; }
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -65,6 +65,7 @@ public:
|
||||||
virtual bool poolable() const { return false; }
|
virtual bool poolable() const { return false; }
|
||||||
|
|
||||||
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
||||||
|
virtual DownstreamAddr *get_addr() const;
|
||||||
|
|
||||||
int send();
|
int send();
|
||||||
|
|
||||||
|
|
|
@ -562,6 +562,24 @@ int HttpDownstreamConnection::end_upload_data() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void remove_from_pool(HttpDownstreamConnection *dconn) {
|
||||||
|
auto group = dconn->get_downstream_addr_group();
|
||||||
|
auto &shared_addr = group->shared_addr;
|
||||||
|
|
||||||
|
if (shared_addr->affinity == AFFINITY_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 &dconn_pool = addr->dconn_pool;
|
||||||
|
dconn_pool->remove_downstream_connection(dconn);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void idle_readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
void idle_readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
auto conn = static_cast<Connection *>(w->data);
|
auto conn = static_cast<Connection *>(w->data);
|
||||||
|
@ -569,9 +587,8 @@ void idle_readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
DCLOG(INFO, dconn) << "Idle connection EOF";
|
DCLOG(INFO, dconn) << "Idle connection EOF";
|
||||||
}
|
}
|
||||||
auto &dconn_pool =
|
|
||||||
dconn->get_downstream_addr_group()->shared_addr->dconn_pool;
|
remove_from_pool(dconn);
|
||||||
dconn_pool.remove_downstream_connection(dconn);
|
|
||||||
// dconn was deleted
|
// dconn was deleted
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -583,9 +600,8 @@ void idle_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
DCLOG(INFO, dconn) << "Idle connection timeout";
|
DCLOG(INFO, dconn) << "Idle connection timeout";
|
||||||
}
|
}
|
||||||
auto &dconn_pool =
|
|
||||||
dconn->get_downstream_addr_group()->shared_addr->dconn_pool;
|
remove_from_pool(dconn);
|
||||||
dconn_pool.remove_downstream_connection(dconn);
|
|
||||||
// dconn was deleted
|
// dconn was deleted
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -65,6 +65,7 @@ public:
|
||||||
virtual bool poolable() const;
|
virtual bool poolable() const;
|
||||||
|
|
||||||
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
virtual DownstreamAddrGroup *get_downstream_addr_group() const;
|
||||||
|
virtual DownstreamAddr *get_addr() const;
|
||||||
|
|
||||||
int read_clear();
|
int read_clear();
|
||||||
int write_clear();
|
int write_clear();
|
||||||
|
@ -80,8 +81,6 @@ public:
|
||||||
|
|
||||||
int noop();
|
int noop();
|
||||||
|
|
||||||
DownstreamAddr *get_addr() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection conn_;
|
Connection conn_;
|
||||||
std::function<int(HttpDownstreamConnection &)> do_read_, do_write_,
|
std::function<int(HttpDownstreamConnection &)> do_read_, do_write_,
|
||||||
|
|
|
@ -96,6 +96,9 @@ struct DownstreamAddr {
|
||||||
// Http2Session object created for this address. This list chains
|
// Http2Session object created for this address. This list chains
|
||||||
// all Http2Session objects that is not in group scope
|
// all Http2Session objects that is not in group scope
|
||||||
// http2_avail_freelist, and is not reached in maximum concurrency.
|
// http2_avail_freelist, and is not reached in maximum concurrency.
|
||||||
|
//
|
||||||
|
// If session affinity is enabled, http2_avail_freelist is not used,
|
||||||
|
// and this list is solely used.
|
||||||
DList<Http2Session> http2_extra_freelist;
|
DList<Http2Session> http2_extra_freelist;
|
||||||
// true if Http2Session for this address is in group scope
|
// true if Http2Session for this address is in group scope
|
||||||
// SharedDownstreamAddr.http2_avail_freelist
|
// SharedDownstreamAddr.http2_avail_freelist
|
||||||
|
@ -129,6 +132,9 @@ struct SharedDownstreamAddr {
|
||||||
// coalesce as much stream as possible in one Http2Session to fully
|
// coalesce as much stream as possible in one Http2Session to fully
|
||||||
// utilize TCP connection.
|
// utilize TCP connection.
|
||||||
//
|
//
|
||||||
|
// If session affinity is enabled, this list is not used. Per
|
||||||
|
// address http2_extra_freelist is used instead.
|
||||||
|
//
|
||||||
// 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;
|
||||||
|
|
Loading…
Reference in New Issue