Skip to content

VIP6: What does pipe mean in Varnish5?

Poul-Henning Kamp edited this page Apr 4, 2016 · 3 revisions

Synopsis

The fact that HTTP/2 is multistreamed means we have to decide what "pipe" means going forward

Why?

In HTTP/1 all transactions are serialized and we can therefore decide, on any transaction, to start piping to a backend.

In HTTP/2 transactions happen in parallel and share not only the TCP connection, but also compression state.

Piping was originally intended to cater for traffic Varnish did not understand, such as TN3270 with a HTTP lead-in and such hacks. With HTTP/2 being used as transport protocol for things like websockets, similar considerations apply.

In HTTP/2 we can imagine two levels of piping, either we pipe the full connection, or we pipe stream by stream.

Piping stream by stream is hard, the streams would have to be decompressed and recompressed. We can do that for HTTP, because we know the semantics, but if another carried protocol, such as websockets, decides to implement their own shared-state compression, we'll need to know about that before we can pipe those streams.

At present we have no documented need to pipe stream-by-stream, so Gettys rule " The only thing worse than generalizing from one example is generalizing from no examples at all." is certainly appropriate.

Connection based piping is much simpler, but the decision criteria needs to be thought about.

In HTTP/1 we can stare at a request in vcl_recv{} and make up our mind.

In HTTP/2 we could do that too, but only for the very first request on the connection.

If the HTTP/2 is being used for another protocol, there will be no request to stare at, and we will only have the IP#'s and possibly the identity of the protocol opening the first stream.

The need for piping in HTTP/1 is also a lot smaller than it used to be, and hopefully in V5 it will never be a good idea to pipe a HTTP transaction, unless there is something truly special (read: Non-compliant) about it.

If we pipe per connection only, we can make it possible to send a PROXY header to the backend.

We have still to decide what "piping" means if the backend is a VMOD.

Error handling if piping is attempted illegal times/places needs to be thought about.

How?

We introduce a new variable "req.can_pipe" in vcl_recv{} which indicates if piping is possible.

For HTTP/1 it will always be set. For HTTP/2 it will be set only for the very first request, and no other requests will be allowed into vcl_recv{} from that connection, until the first request has determined if piping will happen.

If piping is attempted at an illegal time, we fail the session with appropriate noise in VSL.

We add a std.send_proxy_header() which can be called from vcl_pipe{} only.

Clone this wiki locally