nghttpx: Retry next HTTP/2 backend address when connection cannot be made

This commit is contained in:
Tatsuhiro Tsujikawa 2016-04-12 23:30:52 +09:00
parent bda352bf73
commit b6708a4b87
6 changed files with 50 additions and 36 deletions

View File

@ -95,9 +95,7 @@ int Http2DownstreamConnection::attach_downstream(Downstream *downstream) {
DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream;
} }
http2session_->add_downstream_connection(this); http2session_->add_downstream_connection(this);
if (http2session_->get_state() == Http2Session::DISCONNECTED) { http2session_->signal_write();
http2session_->signal_write();
}
downstream_ = downstream; downstream_ = downstream;
downstream_->reset_downstream_rtimer(); downstream_->reset_downstream_rtimer();

View File

@ -73,11 +73,9 @@ void connchk_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
SSLOG(INFO, http2session) << "ping timeout"; SSLOG(INFO, http2session) << "ping timeout";
} }
http2session->disconnect();
if (http2session->get_num_dconns() == 0) { delete http2session;
delete http2session;
}
return; return;
default: default:
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@ -95,10 +93,8 @@ void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
http2session->stop_settings_timer(); http2session->stop_settings_timer();
SSLOG(INFO, http2session) << "SETTINGS timeout"; SSLOG(INFO, http2session) << "SETTINGS timeout";
if (http2session->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) { if (http2session->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) {
http2session->disconnect(); delete http2session;
if (http2session->get_num_dconns() == 0) {
delete http2session;
}
return; return;
} }
http2session->signal_write(); http2session->signal_write();
@ -114,11 +110,7 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
SSLOG(INFO, http2session) << "Timeout"; SSLOG(INFO, http2session) << "Timeout";
} }
http2session->disconnect(http2session->get_state() == delete http2session;
Http2Session::CONNECTING);
if (http2session->get_num_dconns() == 0) {
delete http2session;
}
} }
} // namespace } // namespace
@ -129,20 +121,16 @@ void readcb(struct ev_loop *loop, ev_io *w, int revents) {
auto http2session = static_cast<Http2Session *>(conn->data); auto http2session = static_cast<Http2Session *>(conn->data);
rv = http2session->do_read(); rv = http2session->do_read();
if (rv != 0) { if (rv != 0) {
http2session->disconnect(http2session->should_hard_fail()); delete http2session;
if (http2session->get_num_dconns() == 0) {
delete http2session;
}
return; return;
} }
http2session->connection_alive(); http2session->connection_alive();
rv = http2session->do_write(); rv = http2session->do_write();
if (rv != 0) { if (rv != 0) {
http2session->disconnect(http2session->should_hard_fail()); delete http2session;
if (http2session->get_num_dconns() == 0) {
delete http2session;
}
return; return;
} }
} }
@ -155,10 +143,8 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) {
auto http2session = static_cast<Http2Session *>(conn->data); auto http2session = static_cast<Http2Session *>(conn->data);
rv = http2session->do_write(); rv = http2session->do_write();
if (rv != 0) { if (rv != 0) {
http2session->disconnect(http2session->should_hard_fail()); delete http2session;
if (http2session->get_num_dconns() == 0) {
delete http2session;
}
return; return;
} }
http2session->reset_connection_check_timer_if_not_checking(); http2session->reset_connection_check_timer_if_not_checking();
@ -173,9 +159,9 @@ void initiate_connection_cb(struct ev_loop *loop, ev_timer *w, int revents) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
SSLOG(INFO, http2session) << "Could not initiate backend connection"; SSLOG(INFO, http2session) << "Could not initiate backend connection";
} }
http2session->disconnect(true);
assert(http2session->get_num_dconns() == 0);
delete http2session; delete http2session;
return; return;
} }
} }
@ -223,9 +209,8 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
} }
Http2Session::~Http2Session() { Http2Session::~Http2Session() {
disconnect(true); exclude_from_scheduling();
disconnect(should_hard_fail());
remove_from_freelist();
} }
int Http2Session::disconnect(bool hard) { int Http2Session::disconnect(bool hard) {
@ -1940,9 +1925,11 @@ bool Http2Session::should_hard_fail() const {
switch (state_) { switch (state_) {
case PROXY_CONNECTING: case PROXY_CONNECTING:
case PROXY_FAILED: case PROXY_FAILED:
case CONNECTING:
case CONNECT_FAILING:
return true; return true;
case DISCONNECTED: {
const auto &proxy = get_config()->downstream_http_proxy;
return !proxy.host.empty();
}
default: default:
return false; return false;
} }
@ -2112,9 +2099,16 @@ void Http2Session::remove_from_freelist() {
} }
addr_->http2_extra_freelist.remove(this); addr_->http2_extra_freelist.remove(this);
break; break;
case FREELIST_ZONE_GONE:
return;
} }
freelist_zone_ = FREELIST_ZONE_NONE; freelist_zone_ = FREELIST_ZONE_NONE;
} }
void Http2Session::exclude_from_scheduling() {
remove_from_freelist();
freelist_zone_ = FREELIST_ZONE_GONE;
}
} // namespace shrpx } // namespace shrpx

View File

@ -64,7 +64,10 @@ enum FreelistZone {
FREELIST_ZONE_AVAIL, FREELIST_ZONE_AVAIL,
// Http2Session object is linked in address scope // Http2Session object is linked in address scope
// http2_extra_freelist. // http2_extra_freelist.
FREELIST_ZONE_EXTRA FREELIST_ZONE_EXTRA,
// Http2Session object is about to be deleted, and it does not
// belong to any linked list.
FREELIST_ZONE_GONE
}; };
class Http2Session { class Http2Session {
@ -180,6 +183,10 @@ public:
// linked from any freelist, this function does nothing. // linked from any freelist, this function does nothing.
void remove_from_freelist(); void remove_from_freelist();
// Removes this object form any freelist, and marks this object as
// not schedulable.
void exclude_from_scheduling();
// Returns true if the maximum concurrency is reached. In other // Returns true if the maximum concurrency is reached. In other
// words, the number of currently participated streams in this // words, the number of currently participated streams in this
// session is equal or greater than the max concurrent streams limit // session is equal or greater than the max concurrent streams limit

View File

@ -1759,6 +1759,11 @@ int Http2Upstream::on_downstream_reset(bool no_retry) {
goto fail; goto fail;
} }
rv = downstream->push_request_headers();
if (rv != 0) {
goto fail;
}
continue; continue;
fail: fail:

View File

@ -1197,6 +1197,11 @@ int HttpsUpstream::on_downstream_reset(bool no_retry) {
goto fail; goto fail;
} }
rv = downstream_->push_request_headers();
if (rv != 0) {
goto fail;
}
return 0; return 0;
fail: fail:

View File

@ -1269,6 +1269,11 @@ int SpdyUpstream::on_downstream_reset(bool no_retry) {
goto fail; goto fail;
} }
rv = downstream->push_request_headers();
if (rv != 0) {
goto fail;
}
continue; continue;
fail: fail: