This release fixes several build issues, and add a new library
feature. nghttpx session affinity feature has been improved.
We can now cancel non-DATA frame transmission from
nghttp2_before_frame_send_callback by returning NGHTTP2_ERR_CANCEL
from there. This could be useful for some cases where we know the
transmission of a frame should be avoided. The upcoming use case is
cache digest. After queuing PUSH_PROMISE frame, but before actually
sending the frame, we may know client has the fresh copy of the
resources by CACHE_DIGEST frame. In that case, it is desirable to
cancel transmission of PUSH_PROMISE frame.
nghttp2_on_frame_not_send_callback is invoked if frame transmission
is canceled as usual.
We fixed number of warnings with Sphinx 1.4.0.
nghttpx’s session affinity using client IP is improved by using the
similar hashing technique described in https://github.com/RJ/ketama
This release adds 2 new API functions to libnghttp2. It also adds
HTTP/1.1 POST support to h2load. nghttpx gets new features, and
performance improvements.
We’ve added new API function,
nghttp2_option_set_max_send_header_block_length(). Previously, the
maximum size of header block to send (calculated using the same
algorithm using nghttp2_hd_deflate_bound()) is hard coded as 64KiB.
This is probably sufficient in practice, but sometimes it is desirable
to send more, for example, testing purposes.
nghttp2_option_set_max_send_header_block_length() lets you set this
maximum size by application for its demand.
The another new API function is
nghttp2_session_set_local_window_size(). Previously, application
can increase or even decrease local window size (which is the window
size the remote endpoint must obey when sending DATA to local
endpoint) by using nghttp2_submit_window_size(). But it was a bit
hard to use since it takes the difference against the current window
size. It also affects the current received byte count which is not
acknowledged by WINDOW_UPDATE frame, which is not always desirable.
The new function allows application to set the absolute value of local
window size instead of relative value, and libnghttp2 makes it happen.
It does not affect the current received byte count.
We have client and server implementations under examples directory
written for tutorials. Previously, they only supported NPN TLS
extension. Now they finally get ALPN TLS extension support.
h2load has supported HTTP POST for quite sometime, but it turned out
that its support was limited to HTTP/2 and SPDY. Now we implemented
HTTP POST for HTTP/1.1 as well. There is a known limitation. When
HTTP POST is used with HTTP/1.1 connection, -m option is ignored,
and it is treated as -m1, which means that HTTP pipelining is
disabled.
We added alternative mode to nghttpx frontend, and introduced 2 modes
in this release. This mode is set using --frontend option.
The first alternative mode is health monitor mode. It is enabled per
listener address by specifying healthmon parameter to --frontend
option. If it is enabled, all requests coming from that listener are
replied with HTTP 200 status code with no response body, without
contacting backend server at all. This mode is useful to do health
check for nghttpx itself.
The second alternative mode is API mode. It is enabled per listener
address by specifying api parameter to --frontend option. The
requests coming from this listener are treated specially as API
request. In this release, we have only one API endpoint, which is
PUT /api/v1beta1/backendconfig. The client can post snippet of
nghttpx configuration file containing backend option lines to this
API endpoint. On reception, nghttpx will parse the request body, and
replace the backend servers on the fly without restarting nghttpx
process. The request body is the same format as the file given to
--conf option.
nghttpx gets client IP based session affinity support. It is enabled
per forwarding pattern basis (see <PATTERN> in --backend option)
by adding affinity=ip parameter. If it is enabled, all connections
from the same IP address will be forwarded to the same backend
address. The session affinity may break if one of the backend gets
unreachable, or backend settings are reloaded or replaced by API.
We identified longer TTFB and connect times (you know h2load has these
metrics) when lots of concurrent connections are made to nghttpx. We
fixed this issue in this release, and now nghttpx does not exhibit
longer waiting times in this condition.
This release fixes some bugs both in libnghttp2 and applications, and
fixes minor API issue. We fixed compile error with OpenSSL 1.1.0
pre5. We also improved nghttpx functionality.
API bugs
libnghttp2 offers HPACK API. nghttp2_hd_inflate_hd() decodes
incoming header block data to actual header field name/value pair.
The shortcoming of its API is that its input parameter is not
qualified as const. To fix this issue, we added new
nghttp2_hd_inflate_hd2(). Other than the added const-ness, they
share the same functionality.
Previously, nghttp2_submit_ping() ignored PING flag passed as flags
parameter. This release fixes this bug.
kqueue issues
We use libev for our applications. According to the libev manual,
kqueue is not selected as eligible backend for the BSD based system
other than NetBSD. Because we usually use event for sockets, we
explicitly enabled kqueue backend if it is available. For nghttpx, we
have --no-kqueue option to disable it.
This issue arises if nghttp client sends request body with
content-length header field. If server only sends WINDOW_UPDATE with
the same amount of content-length, tranfer stalls while all data have
been sent. This comes from the design of libnghttp2; its
nghttp2_data_source_read_callback is only called when there is at
least 1 byte of flow control window. But it can completely be
avoided. Since we have content-length, we can just tell libnghttp2
that we have read all data now. This effectively eliminates 0 length
DATA farme
nghttpx: New attributes for mruby object, and other enhancements
In nghttpx, we added new env.server_addr, env.tls_used and
env.server_port attributes. These are all documented in nghttpx
manual page.
The timing when PID file is saved is pushed back, and it is now saved
when setup of all listening sockets has completed. This is useful
when we do graceful shutdown of nghttpx. Now we can just check PID
file is changed, and then issue QUIT signal to the old process.
--backend option now has sni parameter to specify SNI field to
send backend HTTPS server.
Previously, when we call fetch-ocsp-response script, we didn’t pass
environ to the new program. Now we use execv to pass environ.
Previously, the proto and tls parameter in --backend option must
be the same if they are the same routing pattern. Now this
requirement is removed, and we can mix their combinations for the same
pattern.
For HTTP/2 backend, we now consider the backend is alive only when we
receive SETTINGS ACK from backend; just successfully connecting to the
backend is not enough.
This release adds ALTSVC frame support in libnghttp2. nghttp gets new
option to exercise expect/continue dance with server. nghttpx gets
several new features, robust load balancing, and bug fixes.
ALTSVC frame support, and enchanced HTTP/2 extension support
ALTSVC frame is defined in
RFC 7838. nghttp2’s ALTSVC
frame support is very simple, and it does not parse
Alt-Svc-Field-Value, and it just passes the received value to the
application. This is because ALTSVC aware application most likely has
a parser for this since ALTSVC can be sent via regular HTTP header
field Alt-Svc.
By default, incoming ALTSVC frame is ignored. To receive ALTSVC
frame, create nghttp2_option object, and use
nghttp2_option_set_builtin_recv_extension_type(opt, NGHTTP2_ALTSVC),
and pass the object to the nghttp2_session_client_new2() or
nghttp2_session_client_new3(). Note that server always ignores
ALTSVC regardless of the option settings.
To send ALTSVC frame, use nghttp2_submit_altsvc().
nghttp2 has introduced custom frame support in v1.8.0. So you can
create your own ALTSVC handling if you wish.
Previously, we didn’t pass unknown incoming SETTINGS value to the
application. Now those values are also passed to the application via
nghttp2_on_frame_recv_callback.
nghttp : expect/continue exercises
Jacob Champion has implemented expect/continue dance with server in
nghttp client. With new --expect-continue option, nghttp briefly
waits for 100-continue from server before sending request body.
HTTP/2 has flow control, and it is regarded as better feature for
this, but this new option is useful to debug the server’s
expect/continue feature since it is still supported by HTTP/2.
nghttpx: better load balancing, and bug fixes
Brian Suh fixed the bug that nghttpx returned 502 on FreeBSD (and
possibly Mac OS X).
nghttpx now has the feature to detect the backend is online or
offline. nghttpx’s --backend option now gets additional parameter
rise=<N>, and fall=<N>. The fall=<N> specifies that if the
backend cannot be connected in <N> times in a row, it is considered
as offline, and excluded from load balancing group. The rise=<N>
specifies that if nghttpx can connect to the offline backend in <N>
times in a row, the backend is considered as online, and it is
eligible for load balancing again. By default, these feature are
disabled, and backend never be excluded from load balancing group.
Previously, when nghttpx could not connect to the one of backend, it
did not use another backend, and just returns 5xx status code. Now it
tries another backends in case of connect failure.
We fixed the bug that server push from mruby script did not work.
The server push using Link header field is extended, and now nghttpx
can push resources using Link header field in non-final(1xx) response
header fields from backend server.
It is not a secret that we used nginx as backend Web server for
nghttp2.org. We use nghttpx as frontend “Edge” reverse proxy, and all
requests except for the ones to /httpbin were routed to nginx via
HTTP/2 protocol.
Today, we have replaced backend nginx with
h2o. h2o is a relatively new brazing fast
Web server. Actually, we don’t require performance in our low traffic
Web site. The reason we chose h2o is its better HTTP/2
implementation. Since we use HTTP/2 as backend protocol between proxy
and backend server, we’d like to use better backend HTTP/2 server.
h2o supports both HTTP/1.1 as well as HTTP/2 without TLS by default
without extra configuration. Currently, HTTP/2 priority in the
frontend proxy connection is not propagated to the backend connection,
so we couldn’t utilize the great scheduling mechanism built in h2o.
When we implement it, we definitely want clever HTTP/2 scheduler like
h2o.
We still use nghttpx as frontend reverse proxy.
Previously, with nginx, we added link header field in nginx
configuration so that nghttpx could push resource based on it. Now we
initiate push using nghttpx’s mruby scripting feature. The following
script initiates the push for the resource “/stylesheet/screen.css”
when request path is either “/” or “/index.html”:
This release adds new callback functions to libnghttp2 for better
debugging, and potential performance enhancements. We refactored
nghttpx basic interface, and it gets many powerful features in this
release. We fixed several bugs in h2load when it is used against
HTTP/1.1 server. We also now have cmake build support.
New callback functions for better debugging and performance
We have added 2 new callback functions.
nghttp2_error_callback
is a callback that tells application about the detailed error message
for human consumption. This is intended for debugging purpose.
The 2nd new callback function is
nghttp2_on_header_callback2.
This function is similar to existing
nghttp2_on_header_callback.
The crucial difference between these two is that new callback uses
reference counted buffers for header field name/value. Application
can increase their reference count by
nghttp2_rcbuf_incref,
and store its reference without copying the content. When its usage
is done, don’t forget to call
nghttp2_rcbuf_decref.
Previously, the buffer storing header field name/value is owned solely
by libnghttp2 library, and application has to copy them out if it
wants to retain them for future use.
We also added new API function
nghttp2_http2_strerror.
This function returns text version of HTTP/2 error code (e.g.,
PROTOCOL_ERROR). This is useful to output debugging information
about error code contained in RST_STREAM or GOAWAY frame.
Peter Wu has done a stellar job to add cmake build support for
nghttp2. According to the PR documents, cmake build is faster than
autotool build. It also supports Windows build at least for
libnghttp2.
Jan-E fixed several rough edges in Makefile.msvc.
h2load bug fixes
We fixed 2 bugs in h2load when HTTP/1.1 is used. The first bug is
that it did not try to connect to server again. This happens if
server shutdowns the connection if it serves certain number of
requests. This kind of behaviour is enabled by default for some
server software.
The 2nd bug is that initial max concurrent streams was too large, and
it causes undefined behaviour if -m option is not used.
nghttpx: better configuration for frontend/backend protocol and encryption
In this release, we reworked nghttpx command-line (and thus its
configuration) interface. Previously, it had --http2-bridge,
--client, and --client-proxy options to change its major mode.
But they were quite inflexible, and became obstacles when we are
extending nghttpx features. To ensure the further feature
enhancements, they have been removed. Now nghttpx gets much simpler,
and only has 2 modes: default mode, and HTTP/2 proxy mode (-s
option). The removed modes can be achieved using other options. Read
Migration from nghttpx v1.8.0 or earlier
to know how to migrate from earlier release.
Now backend connections are not encrypted by default regardless of the
used protocol. The exciting new feature is that backend protocol can
be specified per routing pattern basis. Also the TLS can be enabled
per routing pattern as well:
With above configuration, requests to /httpbin/ are routed to
unix:/var/unix/httpbinsv via HTTP/1.1 protocol over cleartext TCP.
The other requests are routed to 127.0.0.1:8080 via HTTP/2 protocol
over TLS. tls keyword in --backend option enables encryption.
We now allow wildcard in routing pattern in --backend option. When
we write:
1
backend=127.0.0.1,8080;*.nghttp2.org
All requests which have host (or :authority) header field whose suffix
is .nghttp2.org are routed to 127.0.0.1:8080.
Since the previous release, nghttpx has got multiple frontend
addresses support. Now its feature has been extended, and TLS can be
enabled or disabled per frontend address. This means that single
nghttpx instance finally can serve both TLS and non-TLS contents:
12
frontend=*,443
frontend=*,80;no-tls
With the above configuration, nghttpx listens to port 443 for incoming
TLS connection. It also listens to port 80, but this time for
incoming cleartext connection. no-tls keyword in --frontend
option disables encryption. --frontend-no-tls options has been
removed in favor of no-tls keyword.
The encryption for memcached connections has been available since the
previous release. In this release, we changed how to enable TLS. Now
we use similar syntax for --frontend option. To enable TLS over
memcached connection to get TLS ticket keys, use the following
configuration:
1
tls-ticket-key-memcached=127.0.0.1,11211;tls
In the above configuration, the tls keyword enables encryption.
nghttpx supports server push with Link header field with rel=preload.
Now it recognizes nopush target attribute (see
preload).
There are several deprecated options. If they are used, nghttpx will
output warning level logging message. Please be careful for them, and
they may contain the idea how to migrate to the new or existing other
options.
nghttp2.org has been powered by nghttpx reverse proxy. It forwards
most of the requests to backend nginx. And resources under /httpbin
is forwarded to httpbin server. Previously, all backend forward link
is cleartext HTTP/1.1. Now, with the new feature added to nghttpx, we
forwards requests to nginx in HTTP/2 protocol.
nghttpx in the current nghttp2 master branch has a feature to specify
backend protocol per host/request path routing pattern. So we just
specify the following 2 options to make the above routing work:
The above configuration means that all requests whose path starts with
/httpbin/ are forwarded to UNIX domain socket
unix:/var/unix/httpbinsv.sock via HTTP/1.1 protocol. The rest of
the requets are forwarded to server listening 127.0.0.1:8080 via
HTTP/2 protocol.
The microbench mark shows that using HTTP/2 backend connection reduces
backend TCP connection to about 1/100 (because of the concurrency in
HTTP/2 protocol, and we coalesce frontend connections into fewer
backend HTTP/2 connections), and roughly 2 times faster than HTTP/1.1
backend. HTTP/2 backend is a bit slower with default 64KiB stream
window when transferring large objects, but it could be remedied by
using larger window.