nghttpx: Improve performance with h1 backend when request body is involved

This commit is contained in:
Tatsuhiro Tsujikawa 2016-09-22 19:02:57 +09:00
parent e1dfff8929
commit 231d739b10
4 changed files with 32 additions and 5 deletions

View File

@ -372,6 +372,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
if (!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
req.http2_expect_body = true;
} else if (req.fs.content_length == -1) {
// If END_STREAM flag is set to HEADERS frame, we are sure that
// content-length is 0.
req.fs.content_length = 0;
}
downstream->inspect_http2_request();
@ -643,6 +647,9 @@ int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
req.http_major = 2;
req.http_minor = 0;
req.fs.content_length = 0;
req.http2_expect_body = false;
auto &promised_balloc = promised_downstream->get_block_allocator();
for (size_t i = 0; i < frame->push_promise.nvlen; ++i) {
@ -2072,6 +2079,9 @@ Http2Upstream::on_downstream_push_promise(Downstream *downstream,
promised_req.http_major = 2;
promised_req.http_minor = 0;
promised_req.fs.content_length = 0;
promised_req.http2_expect_body = false;
auto ptr = promised_downstream.get();
add_pending_downstream(std::move(promised_downstream));
downstream_queue_.mark_active(ptr);

View File

@ -525,7 +525,13 @@ int HttpDownstreamConnection::push_request_headers() {
<< downstream_->get_stream_id() << "\n" << nhdrs;
}
signal_write();
// Don't call signal_write() if we anticipate request body. We call
// signal_write() when we received request body chunk, and it
// enables us to send headers and data in one writev system call.
if (connect_method ||
(!req.http2_expect_body && req.fs.content_length == 0)) {
signal_write();
}
return 0;
}

View File

@ -312,10 +312,19 @@ int htp_hdrs_completecb(http_parser *htp) {
ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str();
}
// set content-length if no transfer-encoding is given. If
// transfer-encoding is given, leave req.fs.content_length to -1.
if (!req.fs.header(http2::HD_TRANSFER_ENCODING)) {
req.fs.content_length = htp->content_length;
// set content-length if method is not CONNECT, and no
// transfer-encoding is given. If transfer-encoding is given, leave
// req.fs.content_length to -1.
if (method != HTTP_CONNECT && !req.fs.header(http2::HD_TRANSFER_ENCODING)) {
// http-parser returns (uint64_t)-1 if there is no content-length
// header field. If we don't have both transfer-encoding, and
// content-length header field, we assume that there is no request
// body.
if (htp->content_length == std::numeric_limits<uint64_t>::max()) {
req.fs.content_length = 0;
} else {
req.fs.content_length = htp->content_length;
}
}
auto host = req.fs.header(http2::HD_HOST);

View File

@ -305,6 +305,8 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
if (!(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN)) {
req.http2_expect_body = true;
} else if (req.fs.content_length == -1) {
req.fs.content_length = 0;
}
downstream->inspect_http2_request();