nghttpx: Fix busy loop when HTTP/2 backend reset after connection established

We have now Downstream retry count to be limited to 5 times.  At 6th
failure, we send 503 message to client.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-02-03 01:47:04 +09:00
parent d37fc8f3a6
commit b707cfe986
5 changed files with 24 additions and 7 deletions

View File

@ -112,8 +112,8 @@ Downstream::Downstream(Upstream *upstream, int32_t stream_id, int32_t priority)
request_bodylen_(0), response_bodylen_(0), response_sent_bodylen_(0), request_bodylen_(0), response_bodylen_(0), response_sent_bodylen_(0),
request_content_length_(-1), response_content_length_(-1), request_content_length_(-1), response_content_length_(-1),
upstream_(upstream), request_headers_sum_(0), response_headers_sum_(0), upstream_(upstream), request_headers_sum_(0), response_headers_sum_(0),
request_datalen_(0), response_datalen_(0), stream_id_(stream_id), request_datalen_(0), response_datalen_(0), num_retry_(0),
priority_(priority), downstream_stream_id_(-1), stream_id_(stream_id), priority_(priority), downstream_stream_id_(-1),
response_rst_stream_error_code_(NGHTTP2_NO_ERROR), response_rst_stream_error_code_(NGHTTP2_NO_ERROR),
request_state_(INITIAL), request_major_(1), request_minor_(1), request_state_(INITIAL), request_major_(1), request_minor_(1),
response_state_(INITIAL), response_http_status_(0), response_major_(1), response_state_(INITIAL), response_http_status_(0), response_major_(1),
@ -1020,4 +1020,8 @@ void Downstream::disable_downstream_wtimer() {
bool Downstream::accesslog_ready() const { return response_http_status_ > 0; } bool Downstream::accesslog_ready() const { return response_http_status_ > 0; }
void Downstream::add_retry() { ++num_retry_; }
bool Downstream::no_more_retry() const { return num_retry_ > 5; }
} // namespace shrpx } // namespace shrpx

View File

@ -289,6 +289,11 @@ public:
// Returns true if accesslog can be written for this downstream. // Returns true if accesslog can be written for this downstream.
bool accesslog_ready() const; bool accesslog_ready() const;
// Increment retry count
void add_retry();
// true if retry attempt should not be done.
bool no_more_retry() const;
enum { enum {
EVENT_ERROR = 0x1, EVENT_ERROR = 0x1,
EVENT_TIMEOUT = 0x2, EVENT_TIMEOUT = 0x2,
@ -338,6 +343,8 @@ private:
size_t request_datalen_; size_t request_datalen_;
size_t response_datalen_; size_t response_datalen_;
size_t num_retry_;
int32_t stream_id_; int32_t stream_id_;
int32_t priority_; int32_t priority_;
// stream ID in backend connection // stream ID in backend connection

View File

@ -1420,7 +1420,9 @@ int Http2Upstream::on_downstream_reset(bool no_retry) {
downstream->pop_downstream_connection(); downstream->pop_downstream_connection();
if (no_retry) { downstream->add_retry();
if (no_retry || downstream->no_more_retry()) {
if (on_downstream_abort_request(downstream, 503) != 0) { if (on_downstream_abort_request(downstream, 503) != 0) {
return -1; return -1;
} }

View File

@ -836,15 +836,17 @@ int HttpsUpstream::on_downstream_reset(bool no_retry) {
return -1; return -1;
} }
if (no_retry) { downstream_->pop_downstream_connection();
downstream_->add_retry();
if (no_retry || downstream_->no_more_retry()) {
if (on_downstream_abort_request(downstream_.get(), 503) != 0) { if (on_downstream_abort_request(downstream_.get(), 503) != 0) {
return -1; return -1;
} }
return 0; return 0;
} }
downstream_->pop_downstream_connection();
rv = downstream_->attach_downstream_connection( rv = downstream_->attach_downstream_connection(
handler_->get_downstream_connection()); handler_->get_downstream_connection());
if (rv != 0) { if (rv != 0) {

View File

@ -1051,7 +1051,9 @@ int SpdyUpstream::on_downstream_reset(bool no_retry) {
downstream->pop_downstream_connection(); downstream->pop_downstream_connection();
if (no_retry) { downstream->add_retry();
if (no_retry || downstream->no_more_retry()) {
if (on_downstream_abort_request(downstream, 503) != 0) { if (on_downstream_abort_request(downstream, 503) != 0) {
return -1; return -1;
} }