Adjust read/write timeout depending on the request/response state
This commit is contained in:
parent
22f5bb3ebb
commit
eb9458bba9
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue