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_sec = 30;
mod_config()->downstream_write_timeout.tv_usec = 0; 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_host = "localhost";
mod_config()->downstream_port = 80; mod_config()->downstream_port = 80;

View File

@ -64,6 +64,7 @@ struct Config {
timeval spdy_upstream_write_timeout; timeval spdy_upstream_write_timeout;
timeval downstream_read_timeout; timeval downstream_read_timeout;
timeval downstream_write_timeout; timeval downstream_write_timeout;
timeval downstream_idle_read_timeout;
size_t num_worker; size_t num_worker;
size_t spdy_max_concurrent_streams; size_t spdy_max_concurrent_streams;
Config(); 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() int Downstream::push_request_headers()
{ {
bool xff_found = false; bool xff_found = false;
@ -317,6 +319,8 @@ int Downstream::push_request_headers()
bufferevent *bev = dconn_->get_bev(); bufferevent *bev = dconn_->get_bev();
evbuffer *output = bufferevent_get_output(bev); evbuffer *output = bufferevent_get_output(bev);
evbuffer_add(output, hdrs.c_str(), hdrs.size()); evbuffer_add(output, hdrs.c_str(), hdrs.size());
dconn_->start_waiting_response();
return 0; return 0;
} }

View File

@ -87,13 +87,29 @@ int DownstreamConnection::attach_downstream(Downstream *downstream)
upstream->get_downstream_readcb(), upstream->get_downstream_readcb(),
upstream->get_downstream_writecb(), upstream->get_downstream_writecb(),
upstream->get_downstream_eventcb(), this); 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_, bufferevent_set_timeouts(bev_,
&get_config()->downstream_read_timeout, 0,
&get_config()->downstream_write_timeout); &get_config()->downstream_write_timeout);
return 0; 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 { namespace {
// Gets called when DownstreamConnection is pooled in ClientHandler. // Gets called when DownstreamConnection is pooled in ClientHandler.
void idle_eventcb(bufferevent *bev, short events, void *arg) void idle_eventcb(bufferevent *bev, short events, void *arg)
@ -136,6 +152,11 @@ void DownstreamConnection::detach_downstream(Downstream *downstream)
downstream_ = 0; downstream_ = 0;
bufferevent_enable(bev_, EV_READ); bufferevent_enable(bev_, EV_READ);
bufferevent_setcb(bev_, 0, 0, idle_eventcb, this); 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); client_handler_->pool_downstream_connection(this);
} }

View File

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

View File

@ -269,6 +269,7 @@ void on_data_chunk_recv_callback
std::map<int32_t, Request*>::iterator itr = std::map<int32_t, Request*>::iterator itr =
spdySession->streams.find(stream_id); spdySession->streams.find(stream_id);
if(itr != spdySession->streams.end()) { if(itr != spdySession->streams.end()) {
spdylay_submit_rst_stream(session, stream_id, SPDYLAY_PROTOCOL_ERROR);
Request *req = (*itr).second; Request *req = (*itr).second;
if(req->inflater) { if(req->inflater) {
while(len > 0) { while(len > 0) {
@ -387,7 +388,7 @@ void on_stream_close_callback
(*itr).second->record_complete_time(); (*itr).second->record_complete_time();
++spdySession->complete; ++spdySession->complete;
if(spdySession->all_requests_processed()) { if(spdySession->all_requests_processed()) {
spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK); //spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK);
} }
} }
} }