From eb9458bba9fdb966ffcbcc682b34aa46022aad5a Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 12 Jun 2012 23:02:01 +0900 Subject: [PATCH] Adjust read/write timeout depending on the request/response state --- examples/shrpx.cc | 2 ++ examples/shrpx_config.h | 1 + examples/shrpx_downstream.cc | 4 ++++ examples/shrpx_downstream_connection.cc | 25 +++++++++++++++++++++++-- examples/shrpx_downstream_connection.h | 1 + examples/spdycat.cc | 3 ++- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/examples/shrpx.cc b/examples/shrpx.cc index 686fa4ec..ca814583 100644 --- a/examples/shrpx.cc +++ b/examples/shrpx.cc @@ -251,6 +251,8 @@ void fill_default_config() mod_config()->downstream_write_timeout.tv_sec = 30; mod_config()->downstream_write_timeout.tv_usec = 0; + mod_config()->downstream_idle_read_timeout.tv_sec = 15; + mod_config()->downstream_host = "localhost"; mod_config()->downstream_port = 80; diff --git a/examples/shrpx_config.h b/examples/shrpx_config.h index 9c2bdc8b..97157adc 100644 --- a/examples/shrpx_config.h +++ b/examples/shrpx_config.h @@ -64,6 +64,7 @@ struct Config { timeval spdy_upstream_write_timeout; timeval downstream_read_timeout; timeval downstream_write_timeout; + timeval downstream_idle_read_timeout; size_t num_worker; size_t spdy_max_concurrent_streams; Config(); diff --git a/examples/shrpx_downstream.cc b/examples/shrpx_downstream.cc index 64aaf24a..0d5517cb 100644 --- a/examples/shrpx_downstream.cc +++ b/examples/shrpx_downstream.cc @@ -254,6 +254,8 @@ bool Downstream::get_output_buffer_full() } } +// Call this function after this object is attached to +// Downstream. Otherwise, the program will crash. int Downstream::push_request_headers() { bool xff_found = false; @@ -317,6 +319,8 @@ int Downstream::push_request_headers() bufferevent *bev = dconn_->get_bev(); evbuffer *output = bufferevent_get_output(bev); evbuffer_add(output, hdrs.c_str(), hdrs.size()); + + dconn_->start_waiting_response(); return 0; } diff --git a/examples/shrpx_downstream_connection.cc b/examples/shrpx_downstream_connection.cc index 5bdd7513..ca0c675d 100644 --- a/examples/shrpx_downstream_connection.cc +++ b/examples/shrpx_downstream_connection.cc @@ -87,13 +87,29 @@ int DownstreamConnection::attach_downstream(Downstream *downstream) upstream->get_downstream_readcb(), upstream->get_downstream_writecb(), upstream->get_downstream_eventcb(), this); - + // HTTP request/response model, we first issue request to downstream + // server, so just enable write timeout here. bufferevent_set_timeouts(bev_, - &get_config()->downstream_read_timeout, + 0, &get_config()->downstream_write_timeout); return 0; } +// When downstream request is issued, call this function to set read +// timeout. We don't know when the request is completely received by +// the downstream server. This function may be called before that +// happens. Overall it does not cause problem for most of the time. +// If the downstream server is too slow to recv/send, the connection +// will be dropped by read timeout. +void DownstreamConnection::start_waiting_response() +{ + if(bev_) { + bufferevent_set_timeouts(bev_, + &get_config()->downstream_read_timeout, + 0); + } +} + namespace { // Gets called when DownstreamConnection is pooled in ClientHandler. void idle_eventcb(bufferevent *bev, short events, void *arg) @@ -136,6 +152,11 @@ void DownstreamConnection::detach_downstream(Downstream *downstream) downstream_ = 0; bufferevent_enable(bev_, EV_READ); bufferevent_setcb(bev_, 0, 0, idle_eventcb, this); + // On idle state, just enable read timeout. Normally idle downstream + // connection will get EOF from the downstream server and closed. + bufferevent_set_timeouts(bev_, + &get_config()->downstream_idle_read_timeout, + 0); client_handler_->pool_downstream_connection(this); } diff --git a/examples/shrpx_downstream_connection.h b/examples/shrpx_downstream_connection.h index f866ba08..76a66c66 100644 --- a/examples/shrpx_downstream_connection.h +++ b/examples/shrpx_downstream_connection.h @@ -46,6 +46,7 @@ public: ClientHandler* get_client_handler(); Downstream* get_downstream(); + void start_waiting_response(); private: ClientHandler *client_handler_; bufferevent *bev_; diff --git a/examples/spdycat.cc b/examples/spdycat.cc index 7a21ac93..416c5f6b 100644 --- a/examples/spdycat.cc +++ b/examples/spdycat.cc @@ -269,6 +269,7 @@ void on_data_chunk_recv_callback std::map::iterator itr = spdySession->streams.find(stream_id); if(itr != spdySession->streams.end()) { + spdylay_submit_rst_stream(session, stream_id, SPDYLAY_PROTOCOL_ERROR); Request *req = (*itr).second; if(req->inflater) { while(len > 0) { @@ -387,7 +388,7 @@ void on_stream_close_callback (*itr).second->record_complete_time(); ++spdySession->complete; if(spdySession->all_requests_processed()) { - spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK); + //spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK); } } }