Adjust read/write timeout depending on the request/response state

This commit is contained in:
Tatsuhiro Tsujikawa 2012-06-12 23:02:01 +09:00
parent 22f5bb3ebb
commit eb9458bba9
6 changed files with 33 additions and 3 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}

View File

@ -46,6 +46,7 @@ public:
ClientHandler* get_client_handler();
Downstream* get_downstream();
void start_waiting_response();
private:
ClientHandler *client_handler_;
bufferevent *bev_;

View File

@ -269,6 +269,7 @@ void on_data_chunk_recv_callback
std::map<int32_t, Request*>::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);
}
}
}